xref: /openbmc/qemu/hw/virtio/virtio-qmp.c (revision 824cac68)
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 "hw/virtio/virtio.h"
14 #include "virtio-qmp.h"
15 
16 #include "standard-headers/linux/virtio_ids.h"
17 #include "standard-headers/linux/vhost_types.h"
18 #include "standard-headers/linux/virtio_blk.h"
19 #include "standard-headers/linux/virtio_console.h"
20 #include "standard-headers/linux/virtio_gpu.h"
21 #include "standard-headers/linux/virtio_net.h"
22 #include "standard-headers/linux/virtio_scsi.h"
23 #include "standard-headers/linux/virtio_i2c.h"
24 #include "standard-headers/linux/virtio_balloon.h"
25 #include "standard-headers/linux/virtio_iommu.h"
26 #include "standard-headers/linux/virtio_mem.h"
27 #include "standard-headers/linux/virtio_vsock.h"
28 
29 #include CONFIG_DEVICES
30 
31 #define FEATURE_ENTRY(name, desc) (qmp_virtio_feature_map_t) \
32     { .virtio_bit = name, .feature_desc = desc }
33 
34 enum VhostUserProtocolFeature {
35     VHOST_USER_PROTOCOL_F_MQ = 0,
36     VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
37     VHOST_USER_PROTOCOL_F_RARP = 2,
38     VHOST_USER_PROTOCOL_F_REPLY_ACK = 3,
39     VHOST_USER_PROTOCOL_F_NET_MTU = 4,
40     VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5,
41     VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
42     VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
43     VHOST_USER_PROTOCOL_F_PAGEFAULT = 8,
44     VHOST_USER_PROTOCOL_F_CONFIG = 9,
45     VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10,
46     VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11,
47     VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12,
48     VHOST_USER_PROTOCOL_F_RESET_DEVICE = 13,
49     VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS = 14,
50     VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15,
51     VHOST_USER_PROTOCOL_F_MAX
52 };
53 
54 /* Virtio transport features mapping */
55 static const qmp_virtio_feature_map_t virtio_transport_map[] = {
56     /* Virtio device transport features */
57 #ifndef VIRTIO_CONFIG_NO_LEGACY
58     FEATURE_ENTRY(VIRTIO_F_NOTIFY_ON_EMPTY, \
59             "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. "
60             "descs. on VQ"),
61     FEATURE_ENTRY(VIRTIO_F_ANY_LAYOUT, \
62             "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts"),
63 #endif /* !VIRTIO_CONFIG_NO_LEGACY */
64     FEATURE_ENTRY(VIRTIO_F_VERSION_1, \
65             "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)"),
66     FEATURE_ENTRY(VIRTIO_F_IOMMU_PLATFORM, \
67             "VIRTIO_F_IOMMU_PLATFORM: Device can be used on IOMMU platform"),
68     FEATURE_ENTRY(VIRTIO_F_RING_PACKED, \
69             "VIRTIO_F_RING_PACKED: Device supports packed VQ layout"),
70     FEATURE_ENTRY(VIRTIO_F_IN_ORDER, \
71             "VIRTIO_F_IN_ORDER: Device uses buffers in same order as made "
72             "available by driver"),
73     FEATURE_ENTRY(VIRTIO_F_ORDER_PLATFORM, \
74             "VIRTIO_F_ORDER_PLATFORM: Memory accesses ordered by platform"),
75     FEATURE_ENTRY(VIRTIO_F_SR_IOV, \
76             "VIRTIO_F_SR_IOV: Device supports single root I/O virtualization"),
77     /* Virtio ring transport features */
78     FEATURE_ENTRY(VIRTIO_RING_F_INDIRECT_DESC, \
79             "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported"),
80     FEATURE_ENTRY(VIRTIO_RING_F_EVENT_IDX, \
81             "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled"),
82     { -1, "" }
83 };
84 
85 /* Vhost-user protocol features mapping */
86 static const qmp_virtio_feature_map_t vhost_user_protocol_map[] = {
87     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_MQ, \
88             "VHOST_USER_PROTOCOL_F_MQ: Multiqueue protocol supported"),
89     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_LOG_SHMFD, \
90             "VHOST_USER_PROTOCOL_F_LOG_SHMFD: Shared log memory fd supported"),
91     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RARP, \
92             "VHOST_USER_PROTOCOL_F_RARP: Vhost-user back-end RARP broadcasting "
93             "supported"),
94     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_REPLY_ACK, \
95             "VHOST_USER_PROTOCOL_F_REPLY_ACK: Requested operation status ack. "
96             "supported"),
97     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_NET_MTU, \
98             "VHOST_USER_PROTOCOL_F_NET_MTU: Expose host MTU to guest supported"),
99     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SLAVE_REQ, \
100             "VHOST_USER_PROTOCOL_F_SLAVE_REQ: Socket fd for back-end initiated "
101             "requests supported"),
102     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CROSS_ENDIAN, \
103             "VHOST_USER_PROTOCOL_F_CROSS_ENDIAN: Endianness of VQs for legacy "
104             "devices supported"),
105     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CRYPTO_SESSION, \
106             "VHOST_USER_PROTOCOL_F_CRYPTO_SESSION: Session creation for crypto "
107             "operations supported"),
108     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_PAGEFAULT, \
109             "VHOST_USER_PROTOCOL_F_PAGEFAULT: Request servicing on userfaultfd "
110             "for accessed pages supported"),
111     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIG, \
112             "VHOST_USER_PROTOCOL_F_CONFIG: Vhost-user messaging for virtio "
113             "device configuration space supported"),
114     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD, \
115             "VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD: Slave fd communication "
116             "channel supported"),
117     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_HOST_NOTIFIER, \
118             "VHOST_USER_PROTOCOL_F_HOST_NOTIFIER: Host notifiers for specified "
119             "VQs supported"),
120     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD, \
121             "VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD: Shared inflight I/O buffers "
122             "supported"),
123     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RESET_DEVICE, \
124             "VHOST_USER_PROTOCOL_F_RESET_DEVICE: Disabling all rings and "
125             "resetting internal device state supported"),
126     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS, \
127             "VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS: In-band messaging "
128             "supported"),
129     FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS, \
130             "VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS: Configuration for "
131             "memory slots supported"),
132     { -1, "" }
133 };
134 
135 /* virtio device configuration statuses */
136 static const qmp_virtio_feature_map_t virtio_config_status_map[] = {
137     FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER_OK, \
138             "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready"),
139     FEATURE_ENTRY(VIRTIO_CONFIG_S_FEATURES_OK, \
140             "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete"),
141     FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER, \
142             "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device"),
143     FEATURE_ENTRY(VIRTIO_CONFIG_S_NEEDS_RESET, \
144             "VIRTIO_CONFIG_S_NEEDS_RESET: Irrecoverable error, device needs "
145             "reset"),
146     FEATURE_ENTRY(VIRTIO_CONFIG_S_FAILED, \
147             "VIRTIO_CONFIG_S_FAILED: Error in guest, device failed"),
148     FEATURE_ENTRY(VIRTIO_CONFIG_S_ACKNOWLEDGE, \
149             "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found"),
150     { -1, "" }
151 };
152 
153 /* virtio-blk features mapping */
154 #ifdef CONFIG_VIRTIO_BLK
155 static const qmp_virtio_feature_map_t virtio_blk_feature_map[] = {
156     FEATURE_ENTRY(VIRTIO_BLK_F_SIZE_MAX, \
157             "VIRTIO_BLK_F_SIZE_MAX: Max segment size is size_max"),
158     FEATURE_ENTRY(VIRTIO_BLK_F_SEG_MAX, \
159             "VIRTIO_BLK_F_SEG_MAX: Max segments in a request is seg_max"),
160     FEATURE_ENTRY(VIRTIO_BLK_F_GEOMETRY, \
161             "VIRTIO_BLK_F_GEOMETRY: Legacy geometry available"),
162     FEATURE_ENTRY(VIRTIO_BLK_F_RO, \
163             "VIRTIO_BLK_F_RO: Device is read-only"),
164     FEATURE_ENTRY(VIRTIO_BLK_F_BLK_SIZE, \
165             "VIRTIO_BLK_F_BLK_SIZE: Block size of disk available"),
166     FEATURE_ENTRY(VIRTIO_BLK_F_TOPOLOGY, \
167             "VIRTIO_BLK_F_TOPOLOGY: Topology information available"),
168     FEATURE_ENTRY(VIRTIO_BLK_F_MQ, \
169             "VIRTIO_BLK_F_MQ: Multiqueue supported"),
170     FEATURE_ENTRY(VIRTIO_BLK_F_DISCARD, \
171             "VIRTIO_BLK_F_DISCARD: Discard command supported"),
172     FEATURE_ENTRY(VIRTIO_BLK_F_WRITE_ZEROES, \
173             "VIRTIO_BLK_F_WRITE_ZEROES: Write zeroes command supported"),
174 #ifndef VIRTIO_BLK_NO_LEGACY
175     FEATURE_ENTRY(VIRTIO_BLK_F_BARRIER, \
176             "VIRTIO_BLK_F_BARRIER: Request barriers supported"),
177     FEATURE_ENTRY(VIRTIO_BLK_F_SCSI, \
178             "VIRTIO_BLK_F_SCSI: SCSI packet commands supported"),
179     FEATURE_ENTRY(VIRTIO_BLK_F_FLUSH, \
180             "VIRTIO_BLK_F_FLUSH: Flush command supported"),
181     FEATURE_ENTRY(VIRTIO_BLK_F_CONFIG_WCE, \
182             "VIRTIO_BLK_F_CONFIG_WCE: Cache writeback and writethrough modes "
183             "supported"),
184 #endif /* !VIRTIO_BLK_NO_LEGACY */
185     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
186             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
187     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
188             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
189             "negotiation supported"),
190     { -1, "" }
191 };
192 #endif
193 
194 /* virtio-serial features mapping */
195 #ifdef CONFIG_VIRTIO_SERIAL
196 static const qmp_virtio_feature_map_t virtio_serial_feature_map[] = {
197     FEATURE_ENTRY(VIRTIO_CONSOLE_F_SIZE, \
198             "VIRTIO_CONSOLE_F_SIZE: Host providing console size"),
199     FEATURE_ENTRY(VIRTIO_CONSOLE_F_MULTIPORT, \
200             "VIRTIO_CONSOLE_F_MULTIPORT: Multiple ports for device supported"),
201     FEATURE_ENTRY(VIRTIO_CONSOLE_F_EMERG_WRITE, \
202             "VIRTIO_CONSOLE_F_EMERG_WRITE: Emergency write supported"),
203     { -1, "" }
204 };
205 #endif
206 
207 /* virtio-gpu features mapping */
208 #ifdef CONFIG_VIRTIO_GPU
209 static const qmp_virtio_feature_map_t virtio_gpu_feature_map[] = {
210     FEATURE_ENTRY(VIRTIO_GPU_F_VIRGL, \
211             "VIRTIO_GPU_F_VIRGL: Virgl 3D mode supported"),
212     FEATURE_ENTRY(VIRTIO_GPU_F_EDID, \
213             "VIRTIO_GPU_F_EDID: EDID metadata supported"),
214     FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_UUID, \
215             "VIRTIO_GPU_F_RESOURCE_UUID: Resource UUID assigning supported"),
216     FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_BLOB, \
217             "VIRTIO_GPU_F_RESOURCE_BLOB: Size-based blob resources supported"),
218     FEATURE_ENTRY(VIRTIO_GPU_F_CONTEXT_INIT, \
219             "VIRTIO_GPU_F_CONTEXT_INIT: Context types and synchronization "
220             "timelines supported"),
221     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
222             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
223     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
224             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
225             "negotiation supported"),
226     { -1, "" }
227 };
228 #endif
229 
230 /* virtio-input features mapping */
231 #ifdef CONFIG_VIRTIO_INPUT
232 static const qmp_virtio_feature_map_t virtio_input_feature_map[] = {
233     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
234             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
235     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
236             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
237             "negotiation supported"),
238     { -1, "" }
239 };
240 #endif
241 
242 /* virtio-net features mapping */
243 #ifdef CONFIG_VIRTIO_NET
244 static const qmp_virtio_feature_map_t virtio_net_feature_map[] = {
245     FEATURE_ENTRY(VIRTIO_NET_F_CSUM, \
246             "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum "
247             "supported"),
248     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_CSUM, \
249             "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial "
250             "checksum supported"),
251     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \
252             "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading "
253             "reconfig. supported"),
254     FEATURE_ENTRY(VIRTIO_NET_F_MTU, \
255             "VIRTIO_NET_F_MTU: Device max MTU reporting supported"),
256     FEATURE_ENTRY(VIRTIO_NET_F_MAC, \
257             "VIRTIO_NET_F_MAC: Device has given MAC address"),
258     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO4, \
259             "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4"),
260     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO6, \
261             "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6"),
262     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ECN, \
263             "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN"),
264     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_UFO, \
265             "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO"),
266     FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO4, \
267             "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4"),
268     FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO6, \
269             "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6"),
270     FEATURE_ENTRY(VIRTIO_NET_F_HOST_ECN, \
271             "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN"),
272     FEATURE_ENTRY(VIRTIO_NET_F_HOST_UFO, \
273             "VIRTIO_NET_F_HOST_UFO: Device can receive UFO"),
274     FEATURE_ENTRY(VIRTIO_NET_F_MRG_RXBUF, \
275             "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers"),
276     FEATURE_ENTRY(VIRTIO_NET_F_STATUS, \
277             "VIRTIO_NET_F_STATUS: Configuration status field available"),
278     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VQ, \
279             "VIRTIO_NET_F_CTRL_VQ: Control channel available"),
280     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX, \
281             "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported"),
282     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VLAN, \
283             "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported"),
284     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX_EXTRA, \
285             "VIRTIO_NET_F_CTRL_RX_EXTRA: Extra RX mode control supported"),
286     FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ANNOUNCE, \
287             "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets "
288             "supported"),
289     FEATURE_ENTRY(VIRTIO_NET_F_MQ, \
290             "VIRTIO_NET_F_MQ: Multiqueue with automatic receive steering "
291             "supported"),
292     FEATURE_ENTRY(VIRTIO_NET_F_CTRL_MAC_ADDR, \
293             "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control "
294             "channel"),
295     FEATURE_ENTRY(VIRTIO_NET_F_HASH_REPORT, \
296             "VIRTIO_NET_F_HASH_REPORT: Hash reporting supported"),
297     FEATURE_ENTRY(VIRTIO_NET_F_RSS, \
298             "VIRTIO_NET_F_RSS: RSS RX steering supported"),
299     FEATURE_ENTRY(VIRTIO_NET_F_RSC_EXT, \
300             "VIRTIO_NET_F_RSC_EXT: Extended coalescing info supported"),
301     FEATURE_ENTRY(VIRTIO_NET_F_STANDBY, \
302             "VIRTIO_NET_F_STANDBY: Device acting as standby for primary "
303             "device with same MAC addr. supported"),
304     FEATURE_ENTRY(VIRTIO_NET_F_SPEED_DUPLEX, \
305             "VIRTIO_NET_F_SPEED_DUPLEX: Device set linkspeed and duplex"),
306 #ifndef VIRTIO_NET_NO_LEGACY
307     FEATURE_ENTRY(VIRTIO_NET_F_GSO, \
308             "VIRTIO_NET_F_GSO: Handling GSO-type packets supported"),
309 #endif /* !VIRTIO_NET_NO_LEGACY */
310     FEATURE_ENTRY(VHOST_NET_F_VIRTIO_NET_HDR, \
311             "VHOST_NET_F_VIRTIO_NET_HDR: Virtio-net headers for RX and TX "
312             "packets supported"),
313     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
314             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
315     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
316             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
317             "negotiation supported"),
318     { -1, "" }
319 };
320 #endif
321 
322 /* virtio-scsi features mapping */
323 #ifdef CONFIG_VIRTIO_SCSI
324 static const qmp_virtio_feature_map_t virtio_scsi_feature_map[] = {
325     FEATURE_ENTRY(VIRTIO_SCSI_F_INOUT, \
326             "VIRTIO_SCSI_F_INOUT: Requests including read and writable data "
327             "buffers suppoted"),
328     FEATURE_ENTRY(VIRTIO_SCSI_F_HOTPLUG, \
329             "VIRTIO_SCSI_F_HOTPLUG: Reporting and handling hot-plug events "
330             "supported"),
331     FEATURE_ENTRY(VIRTIO_SCSI_F_CHANGE, \
332             "VIRTIO_SCSI_F_CHANGE: Reporting and handling LUN changes "
333             "supported"),
334     FEATURE_ENTRY(VIRTIO_SCSI_F_T10_PI, \
335             "VIRTIO_SCSI_F_T10_PI: T10 info included in request header"),
336     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
337             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
338     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
339             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
340             "negotiation supported"),
341     { -1, "" }
342 };
343 #endif
344 
345 /* virtio/vhost-user-fs features mapping */
346 #ifdef CONFIG_VHOST_USER_FS
347 static const qmp_virtio_feature_map_t virtio_fs_feature_map[] = {
348     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
349             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
350     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
351             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
352             "negotiation supported"),
353     { -1, "" }
354 };
355 #endif
356 
357 /* virtio/vhost-user-i2c features mapping */
358 #ifdef CONFIG_VIRTIO_I2C_ADAPTER
359 static const qmp_virtio_feature_map_t virtio_i2c_feature_map[] = {
360     FEATURE_ENTRY(VIRTIO_I2C_F_ZERO_LENGTH_REQUEST, \
361             "VIRTIO_I2C_F_ZERO_LEGNTH_REQUEST: Zero length requests supported"),
362     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
363             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
364     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
365             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
366             "negotiation supported"),
367     { -1, "" }
368 };
369 #endif
370 
371 /* virtio/vhost-vsock features mapping */
372 #ifdef CONFIG_VHOST_VSOCK
373 static const qmp_virtio_feature_map_t virtio_vsock_feature_map[] = {
374     FEATURE_ENTRY(VIRTIO_VSOCK_F_SEQPACKET, \
375             "VIRTIO_VSOCK_F_SEQPACKET: SOCK_SEQPACKET supported"),
376     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
377             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
378     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
379             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
380             "negotiation supported"),
381     { -1, "" }
382 };
383 #endif
384 
385 /* virtio-balloon features mapping */
386 #ifdef CONFIG_VIRTIO_BALLOON
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 #endif
404 
405 /* virtio-crypto features mapping */
406 #ifdef CONFIG_VIRTIO_CRYPTO
407 static const qmp_virtio_feature_map_t virtio_crypto_feature_map[] = {
408     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
409             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
410     { -1, "" }
411 };
412 #endif
413 
414 /* virtio-iommu features mapping */
415 #ifdef CONFIG_VIRTIO_IOMMU
416 static const qmp_virtio_feature_map_t virtio_iommu_feature_map[] = {
417     FEATURE_ENTRY(VIRTIO_IOMMU_F_INPUT_RANGE, \
418             "VIRTIO_IOMMU_F_INPUT_RANGE: Range of available virtual addrs. "
419             "available"),
420     FEATURE_ENTRY(VIRTIO_IOMMU_F_DOMAIN_RANGE, \
421             "VIRTIO_IOMMU_F_DOMAIN_RANGE: Number of supported domains "
422             "available"),
423     FEATURE_ENTRY(VIRTIO_IOMMU_F_MAP_UNMAP, \
424             "VIRTIO_IOMMU_F_MAP_UNMAP: Map and unmap requests available"),
425     FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS, \
426             "VIRTIO_IOMMU_F_BYPASS: Endpoints not attached to domains are in "
427             "bypass mode"),
428     FEATURE_ENTRY(VIRTIO_IOMMU_F_PROBE, \
429             "VIRTIO_IOMMU_F_PROBE: Probe requests available"),
430     FEATURE_ENTRY(VIRTIO_IOMMU_F_MMIO, \
431             "VIRTIO_IOMMU_F_MMIO: VIRTIO_IOMMU_MAP_F_MMIO flag available"),
432     FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS_CONFIG, \
433             "VIRTIO_IOMMU_F_BYPASS_CONFIG: Bypass field of IOMMU config "
434             "available"),
435     { -1, "" }
436 };
437 #endif
438 
439 /* virtio-mem features mapping */
440 #ifdef CONFIG_VIRTIO_MEM
441 static const qmp_virtio_feature_map_t virtio_mem_feature_map[] = {
442 #ifndef CONFIG_ACPI
443     FEATURE_ENTRY(VIRTIO_MEM_F_ACPI_PXM, \
444             "VIRTIO_MEM_F_ACPI_PXM: node_id is an ACPI PXM and is valid"),
445 #endif /* !CONFIG_ACPI */
446     FEATURE_ENTRY(VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, \
447             "VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE: Unplugged memory cannot be "
448             "accessed"),
449     { -1, "" }
450 };
451 #endif
452 
453 /* virtio-rng features mapping */
454 #ifdef CONFIG_VIRTIO_RNG
455 static const qmp_virtio_feature_map_t virtio_rng_feature_map[] = {
456     FEATURE_ENTRY(VHOST_F_LOG_ALL, \
457             "VHOST_F_LOG_ALL: Logging write descriptors supported"),
458     FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \
459             "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features "
460             "negotiation supported"),
461     { -1, "" }
462 };
463 #endif
464 
465 #define CONVERT_FEATURES(type, map, is_status, bitmap)   \
466     ({                                                   \
467         type *list = NULL;                               \
468         type *node;                                      \
469         for (i = 0; map[i].virtio_bit != -1; i++) {      \
470             if (is_status) {                             \
471                 bit = map[i].virtio_bit;                 \
472             }                                            \
473             else {                                       \
474                 bit = 1ULL << map[i].virtio_bit;         \
475             }                                            \
476             if ((bitmap & bit) == 0) {                   \
477                 continue;                                \
478             }                                            \
479             node = g_new0(type, 1);                      \
480             node->value = g_strdup(map[i].feature_desc); \
481             node->next = list;                           \
482             list = node;                                 \
483             bitmap ^= bit;                               \
484         }                                                \
485         list;                                            \
486     })
487 
488 VirtioDeviceStatus *qmp_decode_status(uint8_t bitmap)
489 {
490     VirtioDeviceStatus *status;
491     uint8_t bit;
492     int i;
493 
494     status = g_new0(VirtioDeviceStatus, 1);
495     status->statuses = CONVERT_FEATURES(strList, virtio_config_status_map,
496                                         1, bitmap);
497     status->has_unknown_statuses = bitmap != 0;
498     if (status->has_unknown_statuses) {
499         status->unknown_statuses = bitmap;
500     }
501 
502     return status;
503 }
504 
505 VhostDeviceProtocols *qmp_decode_protocols(uint64_t bitmap)
506 {
507     VhostDeviceProtocols *vhu_protocols;
508     uint64_t bit;
509     int i;
510 
511     vhu_protocols = g_new0(VhostDeviceProtocols, 1);
512     vhu_protocols->protocols =
513                     CONVERT_FEATURES(strList,
514                                      vhost_user_protocol_map, 0, bitmap);
515     vhu_protocols->has_unknown_protocols = bitmap != 0;
516     if (vhu_protocols->has_unknown_protocols) {
517         vhu_protocols->unknown_protocols = bitmap;
518     }
519 
520     return vhu_protocols;
521 }
522 
523 VirtioDeviceFeatures *qmp_decode_features(uint16_t device_id, uint64_t bitmap)
524 {
525     VirtioDeviceFeatures *features;
526     uint64_t bit;
527     int i;
528 
529     features = g_new0(VirtioDeviceFeatures, 1);
530     features->has_dev_features = true;
531 
532     /* transport features */
533     features->transports = CONVERT_FEATURES(strList, virtio_transport_map, 0,
534                                             bitmap);
535 
536     /* device features */
537     switch (device_id) {
538 #ifdef CONFIG_VIRTIO_SERIAL
539     case VIRTIO_ID_CONSOLE:
540         features->dev_features =
541             CONVERT_FEATURES(strList, virtio_serial_feature_map, 0, bitmap);
542         break;
543 #endif
544 #ifdef CONFIG_VIRTIO_BLK
545     case VIRTIO_ID_BLOCK:
546         features->dev_features =
547             CONVERT_FEATURES(strList, virtio_blk_feature_map, 0, bitmap);
548         break;
549 #endif
550 #ifdef CONFIG_VIRTIO_GPU
551     case VIRTIO_ID_GPU:
552         features->dev_features =
553             CONVERT_FEATURES(strList, virtio_gpu_feature_map, 0, bitmap);
554         break;
555 #endif
556 #ifdef CONFIG_VIRTIO_NET
557     case VIRTIO_ID_NET:
558         features->dev_features =
559             CONVERT_FEATURES(strList, virtio_net_feature_map, 0, bitmap);
560         break;
561 #endif
562 #ifdef CONFIG_VIRTIO_SCSI
563     case VIRTIO_ID_SCSI:
564         features->dev_features =
565             CONVERT_FEATURES(strList, virtio_scsi_feature_map, 0, bitmap);
566         break;
567 #endif
568 #ifdef CONFIG_VIRTIO_BALLOON
569     case VIRTIO_ID_BALLOON:
570         features->dev_features =
571             CONVERT_FEATURES(strList, virtio_balloon_feature_map, 0, bitmap);
572         break;
573 #endif
574 #ifdef CONFIG_VIRTIO_IOMMU
575     case VIRTIO_ID_IOMMU:
576         features->dev_features =
577             CONVERT_FEATURES(strList, virtio_iommu_feature_map, 0, bitmap);
578         break;
579 #endif
580 #ifdef CONFIG_VIRTIO_INPUT
581     case VIRTIO_ID_INPUT:
582         features->dev_features =
583             CONVERT_FEATURES(strList, virtio_input_feature_map, 0, bitmap);
584         break;
585 #endif
586 #ifdef CONFIG_VHOST_USER_FS
587     case VIRTIO_ID_FS:
588         features->dev_features =
589             CONVERT_FEATURES(strList, virtio_fs_feature_map, 0, bitmap);
590         break;
591 #endif
592 #ifdef CONFIG_VHOST_VSOCK
593     case VIRTIO_ID_VSOCK:
594         features->dev_features =
595             CONVERT_FEATURES(strList, virtio_vsock_feature_map, 0, bitmap);
596         break;
597 #endif
598 #ifdef CONFIG_VIRTIO_CRYPTO
599     case VIRTIO_ID_CRYPTO:
600         features->dev_features =
601             CONVERT_FEATURES(strList, virtio_crypto_feature_map, 0, bitmap);
602         break;
603 #endif
604 #ifdef CONFIG_VIRTIO_MEM
605     case VIRTIO_ID_MEM:
606         features->dev_features =
607             CONVERT_FEATURES(strList, virtio_mem_feature_map, 0, bitmap);
608         break;
609 #endif
610 #ifdef CONFIG_VIRTIO_I2C_ADAPTER
611     case VIRTIO_ID_I2C_ADAPTER:
612         features->dev_features =
613             CONVERT_FEATURES(strList, virtio_i2c_feature_map, 0, bitmap);
614         break;
615 #endif
616 #ifdef CONFIG_VIRTIO_RNG
617     case VIRTIO_ID_RNG:
618         features->dev_features =
619             CONVERT_FEATURES(strList, virtio_rng_feature_map, 0, bitmap);
620         break;
621 #endif
622     /* No features */
623     case VIRTIO_ID_9P:
624     case VIRTIO_ID_PMEM:
625     case VIRTIO_ID_IOMEM:
626     case VIRTIO_ID_RPMSG:
627     case VIRTIO_ID_CLOCK:
628     case VIRTIO_ID_MAC80211_WLAN:
629     case VIRTIO_ID_MAC80211_HWSIM:
630     case VIRTIO_ID_RPROC_SERIAL:
631     case VIRTIO_ID_MEMORY_BALLOON:
632     case VIRTIO_ID_CAIF:
633     case VIRTIO_ID_SIGNAL_DIST:
634     case VIRTIO_ID_PSTORE:
635     case VIRTIO_ID_SOUND:
636     case VIRTIO_ID_BT:
637     case VIRTIO_ID_RPMB:
638     case VIRTIO_ID_VIDEO_ENCODER:
639     case VIRTIO_ID_VIDEO_DECODER:
640     case VIRTIO_ID_SCMI:
641     case VIRTIO_ID_NITRO_SEC_MOD:
642     case VIRTIO_ID_WATCHDOG:
643     case VIRTIO_ID_CAN:
644     case VIRTIO_ID_DMABUF:
645     case VIRTIO_ID_PARAM_SERV:
646     case VIRTIO_ID_AUDIO_POLICY:
647     case VIRTIO_ID_GPIO:
648         break;
649     default:
650         g_assert_not_reached();
651     }
652 
653     features->has_unknown_dev_features = bitmap != 0;
654     if (features->has_unknown_dev_features) {
655         features->unknown_dev_features = bitmap;
656     }
657 
658     return features;
659 }
660