/* * Virtio QMP helpers * * Copyright IBM, Corp. 2007 * * Authors: * Anthony Liguori * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "qemu/osdep.h" #include "hw/virtio/virtio.h" #include "virtio-qmp.h" #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/vhost_types.h" #include "standard-headers/linux/virtio_blk.h" #include "standard-headers/linux/virtio_console.h" #include "standard-headers/linux/virtio_gpu.h" #include "standard-headers/linux/virtio_net.h" #include "standard-headers/linux/virtio_scsi.h" #include "standard-headers/linux/virtio_i2c.h" #include "standard-headers/linux/virtio_balloon.h" #include "standard-headers/linux/virtio_iommu.h" #include "standard-headers/linux/virtio_mem.h" #include "standard-headers/linux/virtio_vsock.h" #include CONFIG_DEVICES #define FEATURE_ENTRY(name, desc) (qmp_virtio_feature_map_t) \ { .virtio_bit = name, .feature_desc = desc } enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_MQ = 0, VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1, VHOST_USER_PROTOCOL_F_RARP = 2, VHOST_USER_PROTOCOL_F_REPLY_ACK = 3, VHOST_USER_PROTOCOL_F_NET_MTU = 4, VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, VHOST_USER_PROTOCOL_F_PAGEFAULT = 8, VHOST_USER_PROTOCOL_F_CONFIG = 9, VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10, VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12, VHOST_USER_PROTOCOL_F_RESET_DEVICE = 13, VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS = 14, VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15, VHOST_USER_PROTOCOL_F_MAX }; /* Virtio transport features mapping */ static const qmp_virtio_feature_map_t virtio_transport_map[] = { /* Virtio device transport features */ #ifndef VIRTIO_CONFIG_NO_LEGACY FEATURE_ENTRY(VIRTIO_F_NOTIFY_ON_EMPTY, \ "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. " "descs. on VQ"), FEATURE_ENTRY(VIRTIO_F_ANY_LAYOUT, \ "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts"), #endif /* !VIRTIO_CONFIG_NO_LEGACY */ FEATURE_ENTRY(VIRTIO_F_VERSION_1, \ "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)"), FEATURE_ENTRY(VIRTIO_F_IOMMU_PLATFORM, \ "VIRTIO_F_IOMMU_PLATFORM: Device can be used on IOMMU platform"), FEATURE_ENTRY(VIRTIO_F_RING_PACKED, \ "VIRTIO_F_RING_PACKED: Device supports packed VQ layout"), FEATURE_ENTRY(VIRTIO_F_IN_ORDER, \ "VIRTIO_F_IN_ORDER: Device uses buffers in same order as made " "available by driver"), FEATURE_ENTRY(VIRTIO_F_ORDER_PLATFORM, \ "VIRTIO_F_ORDER_PLATFORM: Memory accesses ordered by platform"), FEATURE_ENTRY(VIRTIO_F_SR_IOV, \ "VIRTIO_F_SR_IOV: Device supports single root I/O virtualization"), /* Virtio ring transport features */ FEATURE_ENTRY(VIRTIO_RING_F_INDIRECT_DESC, \ "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported"), FEATURE_ENTRY(VIRTIO_RING_F_EVENT_IDX, \ "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled"), { -1, "" } }; /* Vhost-user protocol features mapping */ static const qmp_virtio_feature_map_t vhost_user_protocol_map[] = { FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_MQ, \ "VHOST_USER_PROTOCOL_F_MQ: Multiqueue protocol supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_LOG_SHMFD, \ "VHOST_USER_PROTOCOL_F_LOG_SHMFD: Shared log memory fd supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RARP, \ "VHOST_USER_PROTOCOL_F_RARP: Vhost-user back-end RARP broadcasting " "supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_REPLY_ACK, \ "VHOST_USER_PROTOCOL_F_REPLY_ACK: Requested operation status ack. " "supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_NET_MTU, \ "VHOST_USER_PROTOCOL_F_NET_MTU: Expose host MTU to guest supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SLAVE_REQ, \ "VHOST_USER_PROTOCOL_F_SLAVE_REQ: Socket fd for back-end initiated " "requests supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CROSS_ENDIAN, \ "VHOST_USER_PROTOCOL_F_CROSS_ENDIAN: Endianness of VQs for legacy " "devices supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CRYPTO_SESSION, \ "VHOST_USER_PROTOCOL_F_CRYPTO_SESSION: Session creation for crypto " "operations supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_PAGEFAULT, \ "VHOST_USER_PROTOCOL_F_PAGEFAULT: Request servicing on userfaultfd " "for accessed pages supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIG, \ "VHOST_USER_PROTOCOL_F_CONFIG: Vhost-user messaging for virtio " "device configuration space supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD, \ "VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD: Slave fd communication " "channel supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_HOST_NOTIFIER, \ "VHOST_USER_PROTOCOL_F_HOST_NOTIFIER: Host notifiers for specified " "VQs supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD, \ "VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD: Shared inflight I/O buffers " "supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RESET_DEVICE, \ "VHOST_USER_PROTOCOL_F_RESET_DEVICE: Disabling all rings and " "resetting internal device state supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS, \ "VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS: In-band messaging " "supported"), FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS, \ "VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS: Configuration for " "memory slots supported"), { -1, "" } }; /* virtio device configuration statuses */ static const qmp_virtio_feature_map_t virtio_config_status_map[] = { FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER_OK, \ "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready"), FEATURE_ENTRY(VIRTIO_CONFIG_S_FEATURES_OK, \ "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete"), FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER, \ "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device"), FEATURE_ENTRY(VIRTIO_CONFIG_S_NEEDS_RESET, \ "VIRTIO_CONFIG_S_NEEDS_RESET: Irrecoverable error, device needs " "reset"), FEATURE_ENTRY(VIRTIO_CONFIG_S_FAILED, \ "VIRTIO_CONFIG_S_FAILED: Error in guest, device failed"), FEATURE_ENTRY(VIRTIO_CONFIG_S_ACKNOWLEDGE, \ "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found"), { -1, "" } }; /* virtio-blk features mapping */ #ifdef CONFIG_VIRTIO_BLK static const qmp_virtio_feature_map_t virtio_blk_feature_map[] = { FEATURE_ENTRY(VIRTIO_BLK_F_SIZE_MAX, \ "VIRTIO_BLK_F_SIZE_MAX: Max segment size is size_max"), FEATURE_ENTRY(VIRTIO_BLK_F_SEG_MAX, \ "VIRTIO_BLK_F_SEG_MAX: Max segments in a request is seg_max"), FEATURE_ENTRY(VIRTIO_BLK_F_GEOMETRY, \ "VIRTIO_BLK_F_GEOMETRY: Legacy geometry available"), FEATURE_ENTRY(VIRTIO_BLK_F_RO, \ "VIRTIO_BLK_F_RO: Device is read-only"), FEATURE_ENTRY(VIRTIO_BLK_F_BLK_SIZE, \ "VIRTIO_BLK_F_BLK_SIZE: Block size of disk available"), FEATURE_ENTRY(VIRTIO_BLK_F_TOPOLOGY, \ "VIRTIO_BLK_F_TOPOLOGY: Topology information available"), FEATURE_ENTRY(VIRTIO_BLK_F_MQ, \ "VIRTIO_BLK_F_MQ: Multiqueue supported"), FEATURE_ENTRY(VIRTIO_BLK_F_DISCARD, \ "VIRTIO_BLK_F_DISCARD: Discard command supported"), FEATURE_ENTRY(VIRTIO_BLK_F_WRITE_ZEROES, \ "VIRTIO_BLK_F_WRITE_ZEROES: Write zeroes command supported"), #ifndef VIRTIO_BLK_NO_LEGACY FEATURE_ENTRY(VIRTIO_BLK_F_BARRIER, \ "VIRTIO_BLK_F_BARRIER: Request barriers supported"), FEATURE_ENTRY(VIRTIO_BLK_F_SCSI, \ "VIRTIO_BLK_F_SCSI: SCSI packet commands supported"), FEATURE_ENTRY(VIRTIO_BLK_F_FLUSH, \ "VIRTIO_BLK_F_FLUSH: Flush command supported"), FEATURE_ENTRY(VIRTIO_BLK_F_CONFIG_WCE, \ "VIRTIO_BLK_F_CONFIG_WCE: Cache writeback and writethrough modes " "supported"), #endif /* !VIRTIO_BLK_NO_LEGACY */ FEATURE_ENTRY(VHOST_F_LOG_ALL, \ "VHOST_F_LOG_ALL: Logging write descriptors supported"), FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " "negotiation supported"), { -1, "" } }; #endif /* virtio-serial features mapping */ #ifdef CONFIG_VIRTIO_SERIAL static const qmp_virtio_feature_map_t virtio_serial_feature_map[] = { FEATURE_ENTRY(VIRTIO_CONSOLE_F_SIZE, \ "VIRTIO_CONSOLE_F_SIZE: Host providing console size"), FEATURE_ENTRY(VIRTIO_CONSOLE_F_MULTIPORT, \ "VIRTIO_CONSOLE_F_MULTIPORT: Multiple ports for device supported"), FEATURE_ENTRY(VIRTIO_CONSOLE_F_EMERG_WRITE, \ "VIRTIO_CONSOLE_F_EMERG_WRITE: Emergency write supported"), { -1, "" } }; #endif /* virtio-gpu features mapping */ #ifdef CONFIG_VIRTIO_GPU static const qmp_virtio_feature_map_t virtio_gpu_feature_map[] = { FEATURE_ENTRY(VIRTIO_GPU_F_VIRGL, \ "VIRTIO_GPU_F_VIRGL: Virgl 3D mode supported"), FEATURE_ENTRY(VIRTIO_GPU_F_EDID, \ "VIRTIO_GPU_F_EDID: EDID metadata supported"), FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_UUID, \ "VIRTIO_GPU_F_RESOURCE_UUID: Resource UUID assigning supported"), FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_BLOB, \ "VIRTIO_GPU_F_RESOURCE_BLOB: Size-based blob resources supported"), FEATURE_ENTRY(VIRTIO_GPU_F_CONTEXT_INIT, \ "VIRTIO_GPU_F_CONTEXT_INIT: Context types and synchronization " "timelines supported"), FEATURE_ENTRY(VHOST_F_LOG_ALL, \ "VHOST_F_LOG_ALL: Logging write descriptors supported"), FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " "negotiation supported"), { -1, "" } }; #endif /* virtio-input features mapping */ #ifdef CONFIG_VIRTIO_INPUT static const qmp_virtio_feature_map_t virtio_input_feature_map[] = { FEATURE_ENTRY(VHOST_F_LOG_ALL, \ "VHOST_F_LOG_ALL: Logging write descriptors supported"), FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " "negotiation supported"), { -1, "" } }; #endif /* virtio-net features mapping */ #ifdef CONFIG_VIRTIO_NET static const qmp_virtio_feature_map_t virtio_net_feature_map[] = { FEATURE_ENTRY(VIRTIO_NET_F_CSUM, \ "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum " "supported"), FEATURE_ENTRY(VIRTIO_NET_F_GUEST_CSUM, \ "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial " "checksum supported"), FEATURE_ENTRY(VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \ "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading " "reconfig. supported"), FEATURE_ENTRY(VIRTIO_NET_F_MTU, \ "VIRTIO_NET_F_MTU: Device max MTU reporting supported"), FEATURE_ENTRY(VIRTIO_NET_F_MAC, \ "VIRTIO_NET_F_MAC: Device has given MAC address"), FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO4, \ "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4"), FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO6, \ "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6"), FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ECN, \ "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN"), FEATURE_ENTRY(VIRTIO_NET_F_GUEST_UFO, \ "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO"), FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO4, \ "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4"), FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO6, \ "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6"), FEATURE_ENTRY(VIRTIO_NET_F_HOST_ECN, \ "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN"), FEATURE_ENTRY(VIRTIO_NET_F_HOST_UFO, \ "VIRTIO_NET_F_HOST_UFO: Device can receive UFO"), FEATURE_ENTRY(VIRTIO_NET_F_MRG_RXBUF, \ "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers"), FEATURE_ENTRY(VIRTIO_NET_F_STATUS, \ "VIRTIO_NET_F_STATUS: Configuration status field available"), FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VQ, \ "VIRTIO_NET_F_CTRL_VQ: Control channel available"), FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX, \ "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported"), FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VLAN, \ "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported"), FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX_EXTRA, \ "VIRTIO_NET_F_CTRL_RX_EXTRA: Extra RX mode control supported"), FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ANNOUNCE, \ "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets " "supported"), FEATURE_ENTRY(VIRTIO_NET_F_MQ, \ "VIRTIO_NET_F_MQ: Multiqueue with automatic receive steering " "supported"), FEATURE_ENTRY(VIRTIO_NET_F_CTRL_MAC_ADDR, \ "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control " "channel"), FEATURE_ENTRY(VIRTIO_NET_F_HASH_REPORT, \ "VIRTIO_NET_F_HASH_REPORT: Hash reporting supported"), FEATURE_ENTRY(VIRTIO_NET_F_RSS, \ "VIRTIO_NET_F_RSS: RSS RX steering supported"), FEATURE_ENTRY(VIRTIO_NET_F_RSC_EXT, \ "VIRTIO_NET_F_RSC_EXT: Extended coalescing info supported"), FEATURE_ENTRY(VIRTIO_NET_F_STANDBY, \ "VIRTIO_NET_F_STANDBY: Device acting as standby for primary " "device with same MAC addr. supported"), FEATURE_ENTRY(VIRTIO_NET_F_SPEED_DUPLEX, \ "VIRTIO_NET_F_SPEED_DUPLEX: Device set linkspeed and duplex"), #ifndef VIRTIO_NET_NO_LEGACY FEATURE_ENTRY(VIRTIO_NET_F_GSO, \ "VIRTIO_NET_F_GSO: Handling GSO-type packets supported"), #endif /* !VIRTIO_NET_NO_LEGACY */ FEATURE_ENTRY(VHOST_NET_F_VIRTIO_NET_HDR, \ "VHOST_NET_F_VIRTIO_NET_HDR: Virtio-net headers for RX and TX " "packets supported"), FEATURE_ENTRY(VHOST_F_LOG_ALL, \ "VHOST_F_LOG_ALL: Logging write descriptors supported"), FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " "negotiation supported"), { -1, "" } }; #endif /* virtio-scsi features mapping */ #ifdef CONFIG_VIRTIO_SCSI static const qmp_virtio_feature_map_t virtio_scsi_feature_map[] = { FEATURE_ENTRY(VIRTIO_SCSI_F_INOUT, \ "VIRTIO_SCSI_F_INOUT: Requests including read and writable data " "buffers suppoted"), FEATURE_ENTRY(VIRTIO_SCSI_F_HOTPLUG, \ "VIRTIO_SCSI_F_HOTPLUG: Reporting and handling hot-plug events " "supported"), FEATURE_ENTRY(VIRTIO_SCSI_F_CHANGE, \ "VIRTIO_SCSI_F_CHANGE: Reporting and handling LUN changes " "supported"), FEATURE_ENTRY(VIRTIO_SCSI_F_T10_PI, \ "VIRTIO_SCSI_F_T10_PI: T10 info included in request header"), FEATURE_ENTRY(VHOST_F_LOG_ALL, \ "VHOST_F_LOG_ALL: Logging write descriptors supported"), FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " "negotiation supported"), { -1, "" } }; #endif /* virtio/vhost-user-fs features mapping */ #ifdef CONFIG_VHOST_USER_FS static const qmp_virtio_feature_map_t virtio_fs_feature_map[] = { FEATURE_ENTRY(VHOST_F_LOG_ALL, \ "VHOST_F_LOG_ALL: Logging write descriptors supported"), FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " "negotiation supported"), { -1, "" } }; #endif /* virtio/vhost-user-i2c features mapping */ #ifdef CONFIG_VIRTIO_I2C_ADAPTER static const qmp_virtio_feature_map_t virtio_i2c_feature_map[] = { FEATURE_ENTRY(VIRTIO_I2C_F_ZERO_LENGTH_REQUEST, \ "VIRTIO_I2C_F_ZERO_LEGNTH_REQUEST: Zero length requests supported"), FEATURE_ENTRY(VHOST_F_LOG_ALL, \ "VHOST_F_LOG_ALL: Logging write descriptors supported"), FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " "negotiation supported"), { -1, "" } }; #endif /* virtio/vhost-vsock features mapping */ #ifdef CONFIG_VHOST_VSOCK static const qmp_virtio_feature_map_t virtio_vsock_feature_map[] = { FEATURE_ENTRY(VIRTIO_VSOCK_F_SEQPACKET, \ "VIRTIO_VSOCK_F_SEQPACKET: SOCK_SEQPACKET supported"), FEATURE_ENTRY(VHOST_F_LOG_ALL, \ "VHOST_F_LOG_ALL: Logging write descriptors supported"), FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " "negotiation supported"), { -1, "" } }; #endif /* virtio-balloon features mapping */ #ifdef CONFIG_VIRTIO_BALLOON static const qmp_virtio_feature_map_t virtio_balloon_feature_map[] = { FEATURE_ENTRY(VIRTIO_BALLOON_F_MUST_TELL_HOST, \ "VIRTIO_BALLOON_F_MUST_TELL_HOST: Tell host before reclaiming " "pages"), FEATURE_ENTRY(VIRTIO_BALLOON_F_STATS_VQ, \ "VIRTIO_BALLOON_F_STATS_VQ: Guest memory stats VQ available"), FEATURE_ENTRY(VIRTIO_BALLOON_F_DEFLATE_ON_OOM, \ "VIRTIO_BALLOON_F_DEFLATE_ON_OOM: Deflate balloon when guest OOM"), FEATURE_ENTRY(VIRTIO_BALLOON_F_FREE_PAGE_HINT, \ "VIRTIO_BALLOON_F_FREE_PAGE_HINT: VQ reporting free pages enabled"), FEATURE_ENTRY(VIRTIO_BALLOON_F_PAGE_POISON, \ "VIRTIO_BALLOON_F_PAGE_POISON: Guest page poisoning enabled"), FEATURE_ENTRY(VIRTIO_BALLOON_F_REPORTING, \ "VIRTIO_BALLOON_F_REPORTING: Page reporting VQ enabled"), { -1, "" } }; #endif /* virtio-crypto features mapping */ #ifdef CONFIG_VIRTIO_CRYPTO static const qmp_virtio_feature_map_t virtio_crypto_feature_map[] = { FEATURE_ENTRY(VHOST_F_LOG_ALL, \ "VHOST_F_LOG_ALL: Logging write descriptors supported"), { -1, "" } }; #endif /* virtio-iommu features mapping */ #ifdef CONFIG_VIRTIO_IOMMU static const qmp_virtio_feature_map_t virtio_iommu_feature_map[] = { FEATURE_ENTRY(VIRTIO_IOMMU_F_INPUT_RANGE, \ "VIRTIO_IOMMU_F_INPUT_RANGE: Range of available virtual addrs. " "available"), FEATURE_ENTRY(VIRTIO_IOMMU_F_DOMAIN_RANGE, \ "VIRTIO_IOMMU_F_DOMAIN_RANGE: Number of supported domains " "available"), FEATURE_ENTRY(VIRTIO_IOMMU_F_MAP_UNMAP, \ "VIRTIO_IOMMU_F_MAP_UNMAP: Map and unmap requests available"), FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS, \ "VIRTIO_IOMMU_F_BYPASS: Endpoints not attached to domains are in " "bypass mode"), FEATURE_ENTRY(VIRTIO_IOMMU_F_PROBE, \ "VIRTIO_IOMMU_F_PROBE: Probe requests available"), FEATURE_ENTRY(VIRTIO_IOMMU_F_MMIO, \ "VIRTIO_IOMMU_F_MMIO: VIRTIO_IOMMU_MAP_F_MMIO flag available"), FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS_CONFIG, \ "VIRTIO_IOMMU_F_BYPASS_CONFIG: Bypass field of IOMMU config " "available"), { -1, "" } }; #endif /* virtio-mem features mapping */ #ifdef CONFIG_VIRTIO_MEM static const qmp_virtio_feature_map_t virtio_mem_feature_map[] = { #ifndef CONFIG_ACPI FEATURE_ENTRY(VIRTIO_MEM_F_ACPI_PXM, \ "VIRTIO_MEM_F_ACPI_PXM: node_id is an ACPI PXM and is valid"), #endif /* !CONFIG_ACPI */ FEATURE_ENTRY(VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, \ "VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE: Unplugged memory cannot be " "accessed"), { -1, "" } }; #endif /* virtio-rng features mapping */ #ifdef CONFIG_VIRTIO_RNG static const qmp_virtio_feature_map_t virtio_rng_feature_map[] = { FEATURE_ENTRY(VHOST_F_LOG_ALL, \ "VHOST_F_LOG_ALL: Logging write descriptors supported"), FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " "negotiation supported"), { -1, "" } }; #endif #define CONVERT_FEATURES(type, map, is_status, bitmap) \ ({ \ type *list = NULL; \ type *node; \ for (i = 0; map[i].virtio_bit != -1; i++) { \ if (is_status) { \ bit = map[i].virtio_bit; \ } \ else { \ bit = 1ULL << map[i].virtio_bit; \ } \ if ((bitmap & bit) == 0) { \ continue; \ } \ node = g_new0(type, 1); \ node->value = g_strdup(map[i].feature_desc); \ node->next = list; \ list = node; \ bitmap ^= bit; \ } \ list; \ }) VirtioDeviceStatus *qmp_decode_status(uint8_t bitmap) { VirtioDeviceStatus *status; uint8_t bit; int i; status = g_new0(VirtioDeviceStatus, 1); status->statuses = CONVERT_FEATURES(strList, virtio_config_status_map, 1, bitmap); status->has_unknown_statuses = bitmap != 0; if (status->has_unknown_statuses) { status->unknown_statuses = bitmap; } return status; } VhostDeviceProtocols *qmp_decode_protocols(uint64_t bitmap) { VhostDeviceProtocols *vhu_protocols; uint64_t bit; int i; vhu_protocols = g_new0(VhostDeviceProtocols, 1); vhu_protocols->protocols = CONVERT_FEATURES(strList, vhost_user_protocol_map, 0, bitmap); vhu_protocols->has_unknown_protocols = bitmap != 0; if (vhu_protocols->has_unknown_protocols) { vhu_protocols->unknown_protocols = bitmap; } return vhu_protocols; } VirtioDeviceFeatures *qmp_decode_features(uint16_t device_id, uint64_t bitmap) { VirtioDeviceFeatures *features; uint64_t bit; int i; features = g_new0(VirtioDeviceFeatures, 1); features->has_dev_features = true; /* transport features */ features->transports = CONVERT_FEATURES(strList, virtio_transport_map, 0, bitmap); /* device features */ switch (device_id) { #ifdef CONFIG_VIRTIO_SERIAL case VIRTIO_ID_CONSOLE: features->dev_features = CONVERT_FEATURES(strList, virtio_serial_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_BLK case VIRTIO_ID_BLOCK: features->dev_features = CONVERT_FEATURES(strList, virtio_blk_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_GPU case VIRTIO_ID_GPU: features->dev_features = CONVERT_FEATURES(strList, virtio_gpu_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_NET case VIRTIO_ID_NET: features->dev_features = CONVERT_FEATURES(strList, virtio_net_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_SCSI case VIRTIO_ID_SCSI: features->dev_features = CONVERT_FEATURES(strList, virtio_scsi_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_BALLOON case VIRTIO_ID_BALLOON: features->dev_features = CONVERT_FEATURES(strList, virtio_balloon_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_IOMMU case VIRTIO_ID_IOMMU: features->dev_features = CONVERT_FEATURES(strList, virtio_iommu_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_INPUT case VIRTIO_ID_INPUT: features->dev_features = CONVERT_FEATURES(strList, virtio_input_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VHOST_USER_FS case VIRTIO_ID_FS: features->dev_features = CONVERT_FEATURES(strList, virtio_fs_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VHOST_VSOCK case VIRTIO_ID_VSOCK: features->dev_features = CONVERT_FEATURES(strList, virtio_vsock_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_CRYPTO case VIRTIO_ID_CRYPTO: features->dev_features = CONVERT_FEATURES(strList, virtio_crypto_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_MEM case VIRTIO_ID_MEM: features->dev_features = CONVERT_FEATURES(strList, virtio_mem_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_I2C_ADAPTER case VIRTIO_ID_I2C_ADAPTER: features->dev_features = CONVERT_FEATURES(strList, virtio_i2c_feature_map, 0, bitmap); break; #endif #ifdef CONFIG_VIRTIO_RNG case VIRTIO_ID_RNG: features->dev_features = CONVERT_FEATURES(strList, virtio_rng_feature_map, 0, bitmap); break; #endif /* No features */ case VIRTIO_ID_9P: case VIRTIO_ID_PMEM: case VIRTIO_ID_IOMEM: case VIRTIO_ID_RPMSG: case VIRTIO_ID_CLOCK: case VIRTIO_ID_MAC80211_WLAN: case VIRTIO_ID_MAC80211_HWSIM: case VIRTIO_ID_RPROC_SERIAL: case VIRTIO_ID_MEMORY_BALLOON: case VIRTIO_ID_CAIF: case VIRTIO_ID_SIGNAL_DIST: case VIRTIO_ID_PSTORE: case VIRTIO_ID_SOUND: case VIRTIO_ID_BT: case VIRTIO_ID_RPMB: case VIRTIO_ID_VIDEO_ENCODER: case VIRTIO_ID_VIDEO_DECODER: case VIRTIO_ID_SCMI: case VIRTIO_ID_NITRO_SEC_MOD: case VIRTIO_ID_WATCHDOG: case VIRTIO_ID_CAN: case VIRTIO_ID_DMABUF: case VIRTIO_ID_PARAM_SERV: case VIRTIO_ID_AUDIO_POLICY: case VIRTIO_ID_GPIO: break; default: g_assert_not_reached(); } features->has_unknown_dev_features = bitmap != 0; if (features->has_unknown_dev_features) { features->unknown_dev_features = bitmap; } return features; }