aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Virtio Support |
| 3 | * |
| 4 | * Copyright IBM, Corp. 2007 |
| 5 | * |
| 6 | * Authors: |
| 7 | * Anthony Liguori <aliguori@us.ibm.com> |
| 8 | * |
| 9 | * This work is licensed under the terms of the GNU GPL, version 2. See |
| 10 | * the COPYING file in the top-level directory. |
| 11 | * |
| 12 | */ |
| 13 | |
Markus Armbruster | 2a6a407 | 2016-06-29 13:47:03 +0200 | [diff] [blame] | 14 | #ifndef QEMU_VIRTIO_H |
| 15 | #define QEMU_VIRTIO_H |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 16 | |
Markus Armbruster | d484205 | 2019-08-12 07:23:46 +0200 | [diff] [blame] | 17 | #include "exec/memory.h" |
Markus Armbruster | a27bd6c | 2019-08-12 07:23:51 +0200 | [diff] [blame] | 18 | #include "hw/qdev-core.h" |
Paolo Bonzini | 1422e32 | 2012-10-24 08:43:34 +0200 | [diff] [blame] | 19 | #include "net/net.h" |
Markus Armbruster | d645427 | 2019-08-12 07:23:45 +0200 | [diff] [blame] | 20 | #include "migration/vmstate.h" |
Paolo Bonzini | 1de7afc | 2012-12-17 18:20:00 +0100 | [diff] [blame] | 21 | #include "qemu/event_notifier.h" |
Michael S. Tsirkin | e9600c6 | 2015-02-16 22:35:46 +0100 | [diff] [blame] | 22 | #include "standard-headers/linux/virtio_config.h" |
| 23 | #include "standard-headers/linux/virtio_ring.h" |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 24 | #include "qom/object.h" |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 25 | |
Alex Bennée | ea5d6ea | 2022-08-02 10:49:53 +0100 | [diff] [blame] | 26 | /* |
| 27 | * A guest should never accept this. It implies negotiation is broken |
| 28 | * between the driver frontend and the device. This bit is re-used for |
| 29 | * vhost-user to advertise VHOST_USER_F_PROTOCOL_FEATURES between QEMU |
| 30 | * and a vhost-user backend. |
| 31 | */ |
Yeqi Fu | 48805df | 2023-03-15 11:26:49 +0800 | [diff] [blame] | 32 | #define VIRTIO_F_BAD_FEATURE 30 |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 33 | |
Michael S. Tsirkin | 5f45607 | 2015-07-22 13:09:25 +0300 | [diff] [blame] | 34 | #define VIRTIO_LEGACY_FEATURES ((0x1ULL << VIRTIO_F_BAD_FEATURE) | \ |
| 35 | (0x1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | \ |
| 36 | (0x1ULL << VIRTIO_F_ANY_LAYOUT)) |
| 37 | |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 38 | struct VirtQueue; |
| 39 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 40 | static inline hwaddr vring_align(hwaddr addr, |
aliguori | f46f15b | 2008-12-04 19:58:45 +0000 | [diff] [blame] | 41 | unsigned long align) |
| 42 | { |
Andrew Baumann | b8adbc6 | 2017-03-24 16:19:43 -0700 | [diff] [blame] | 43 | return QEMU_ALIGN_UP(addr, align); |
aliguori | f46f15b | 2008-12-04 19:58:45 +0000 | [diff] [blame] | 44 | } |
| 45 | |
Stefano Garzarella | ba55085 | 2019-02-21 11:33:08 +0100 | [diff] [blame] | 46 | typedef struct VirtIOFeature { |
| 47 | uint64_t flags; |
| 48 | size_t end; |
| 49 | } VirtIOFeature; |
| 50 | |
Daniil Tatianin | d74c30c | 2022-09-06 10:31:07 +0300 | [diff] [blame] | 51 | typedef struct VirtIOConfigSizeParams { |
| 52 | size_t min_size; |
| 53 | size_t max_size; |
| 54 | const VirtIOFeature *feature_sizes; |
| 55 | } VirtIOConfigSizeParams; |
| 56 | |
| 57 | size_t virtio_get_config_size(const VirtIOConfigSizeParams *params, |
| 58 | uint64_t host_features); |
Stefano Garzarella | ba55085 | 2019-02-21 11:33:08 +0100 | [diff] [blame] | 59 | |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 60 | typedef struct VirtQueue VirtQueue; |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 61 | |
| 62 | #define VIRTQUEUE_MAX_SIZE 1024 |
| 63 | |
| 64 | typedef struct VirtQueueElement |
| 65 | { |
| 66 | unsigned int index; |
Jason Wang | 86044b2 | 2019-10-25 10:35:24 +0200 | [diff] [blame] | 67 | unsigned int len; |
| 68 | unsigned int ndescs; |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 69 | unsigned int out_num; |
| 70 | unsigned int in_num; |
Paolo Bonzini | 3724650 | 2016-01-31 11:29:00 +0100 | [diff] [blame] | 71 | hwaddr *in_addr; |
| 72 | hwaddr *out_addr; |
| 73 | struct iovec *in_sg; |
| 74 | struct iovec *out_sg; |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 75 | } VirtQueueElement; |
| 76 | |
Jason Wang | b829c2a | 2015-05-29 14:15:32 +0800 | [diff] [blame] | 77 | #define VIRTIO_QUEUE_MAX 1024 |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 78 | |
Michael S. Tsirkin | 7055e68 | 2009-06-21 19:50:13 +0300 | [diff] [blame] | 79 | #define VIRTIO_NO_VECTOR 0xffff |
| 80 | |
Cindy Lu | 544f027 | 2022-12-22 15:04:42 +0800 | [diff] [blame] | 81 | /* special index value used internally for config irqs */ |
| 82 | #define VIRTIO_CONFIG_IRQ_IDX -1 |
| 83 | |
KONRAD Frederic | 8e05db9 | 2013-01-15 00:08:02 +0100 | [diff] [blame] | 84 | #define TYPE_VIRTIO_DEVICE "virtio-device" |
Eduardo Habkost | a489d19 | 2020-09-16 14:25:18 -0400 | [diff] [blame] | 85 | OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE) |
KONRAD Frederic | 8e05db9 | 2013-01-15 00:08:02 +0100 | [diff] [blame] | 86 | |
Laurent Vivier | f3034ad | 2022-08-11 08:24:41 -0400 | [diff] [blame] | 87 | typedef struct { |
| 88 | int virtio_bit; |
| 89 | const char *feature_desc; |
| 90 | } qmp_virtio_feature_map_t; |
| 91 | |
Greg Kurz | 616a655 | 2014-06-24 19:38:54 +0200 | [diff] [blame] | 92 | enum virtio_device_endian { |
| 93 | VIRTIO_DEVICE_ENDIAN_UNKNOWN, |
| 94 | VIRTIO_DEVICE_ENDIAN_LITTLE, |
| 95 | VIRTIO_DEVICE_ENDIAN_BIG, |
| 96 | }; |
| 97 | |
Alex Bennée | 9600c98 | 2022-11-23 15:21:33 +0000 | [diff] [blame] | 98 | /** |
| 99 | * struct VirtIODevice - common VirtIO structure |
| 100 | * @name: name of the device |
| 101 | * @status: VirtIO Device Status field |
| 102 | * |
| 103 | */ |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 104 | struct VirtIODevice |
| 105 | { |
KONRAD Frederic | 8e05db9 | 2013-01-15 00:08:02 +0100 | [diff] [blame] | 106 | DeviceState parent_obj; |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 107 | const char *name; |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 108 | uint8_t status; |
| 109 | uint8_t isr; |
| 110 | uint16_t queue_sel; |
Alex Bennée | 9600c98 | 2022-11-23 15:21:33 +0000 | [diff] [blame] | 111 | /** |
| 112 | * These fields represent a set of VirtIO features at various |
| 113 | * levels of the stack. @host_features indicates the complete |
| 114 | * feature set the VirtIO device can offer to the driver. |
| 115 | * @guest_features indicates which features the VirtIO driver has |
| 116 | * selected by writing to the feature register. Finally |
| 117 | * @backend_features represents everything supported by the |
| 118 | * backend (e.g. vhost) and could potentially be a subset of the |
| 119 | * total feature set offered by QEMU. |
| 120 | */ |
Gerd Hoffmann | 019a3ed | 2015-06-01 10:45:40 +0200 | [diff] [blame] | 121 | uint64_t host_features; |
Alex Bennée | 9600c98 | 2022-11-23 15:21:33 +0000 | [diff] [blame] | 122 | uint64_t guest_features; |
Maxime Coquelin | 75ebec1 | 2017-05-23 14:31:19 +0200 | [diff] [blame] | 123 | uint64_t backend_features; |
Alex Bennée | 9600c98 | 2022-11-23 15:21:33 +0000 | [diff] [blame] | 124 | |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 125 | size_t config_len; |
| 126 | void *config; |
Michael S. Tsirkin | 7055e68 | 2009-06-21 19:50:13 +0300 | [diff] [blame] | 127 | uint16_t config_vector; |
Michael S. Tsirkin | b8f0590 | 2015-06-04 12:34:23 +0200 | [diff] [blame] | 128 | uint32_t generation; |
Michael S. Tsirkin | 7055e68 | 2009-06-21 19:50:13 +0300 | [diff] [blame] | 129 | int nvectors; |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 130 | VirtQueue *vq; |
Paolo Bonzini | c611c76 | 2017-01-27 16:40:17 +0100 | [diff] [blame] | 131 | MemoryListener listener; |
Paul Brook | 53c25ce | 2009-05-18 14:51:59 +0100 | [diff] [blame] | 132 | uint16_t device_id; |
Alex Bennée | 9f6bcfd | 2022-08-02 10:49:58 +0100 | [diff] [blame] | 133 | /* @vm_running: current VM running state via virtio_vmstate_change() */ |
Michael S. Tsirkin | 85cf2a8 | 2011-01-10 14:28:40 +0200 | [diff] [blame] | 134 | bool vm_running; |
Stefan Hajnoczi | f5ed366 | 2016-09-21 16:52:19 +0100 | [diff] [blame] | 135 | bool broken; /* device in invalid state, needs reset */ |
Michael Roth | 9d7bd08 | 2019-11-19 18:50:03 -0600 | [diff] [blame] | 136 | bool use_disabled_flag; /* allow use of 'disable' flag when needed */ |
| 137 | bool disabled; /* device in temporarily disabled state */ |
Alex Bennée | 4987e5b | 2022-11-30 11:24:39 +0000 | [diff] [blame] | 138 | /** |
| 139 | * @use_started: true if the @started flag should be used to check the |
| 140 | * current state of the VirtIO device. Otherwise status bits |
| 141 | * should be checked for a current status of the device. |
| 142 | * @use_started is only set via QMP and defaults to true for all |
| 143 | * modern machines (since 4.1). |
| 144 | */ |
Xie Yongji | e57f2c3 | 2019-06-26 10:31:26 +0800 | [diff] [blame] | 145 | bool use_started; |
Xie Yongji | badaf79 | 2019-03-20 19:26:40 +0800 | [diff] [blame] | 146 | bool started; |
Xie Yongji | 7abccd0 | 2019-06-26 10:31:27 +0800 | [diff] [blame] | 147 | bool start_on_kick; /* when virtio 1.0 feature has not been negotiated */ |
Stefano Garzarella | d55f518 | 2020-09-21 14:25:03 +0200 | [diff] [blame] | 148 | bool disable_legacy_check; |
Jonah Palmer | c255488 | 2022-04-01 09:23:19 -0400 | [diff] [blame] | 149 | bool vhost_started; |
Michael S. Tsirkin | 85cf2a8 | 2011-01-10 14:28:40 +0200 | [diff] [blame] | 150 | VMChangeStateEntry *vmstate; |
KONRAD Frederic | 1034e9c | 2013-04-30 16:08:48 +0200 | [diff] [blame] | 151 | char *bus_name; |
Greg Kurz | 616a655 | 2014-06-24 19:38:54 +0200 | [diff] [blame] | 152 | uint8_t device_endian; |
Alex Bennée | 661dee7 | 2023-07-10 16:35:08 +0100 | [diff] [blame] | 153 | /** |
| 154 | * @user_guest_notifier_mask: gate usage of ->guest_notifier_mask() callback. |
| 155 | * This is used to suppress the masking of guest updates for |
| 156 | * vhost-user devices which are asynchronous by design. |
| 157 | */ |
Victor Kaplansky | 5669655 | 2016-02-18 16:12:23 +0200 | [diff] [blame] | 158 | bool use_guest_notifier_mask; |
Jason Wang | 8607f5c | 2016-12-30 18:09:10 +0800 | [diff] [blame] | 159 | AddressSpace *dma_as; |
Michael S. Tsirkin | 850d007 | 2015-04-27 21:01:20 +0200 | [diff] [blame] | 160 | QLIST_HEAD(, VirtQueue) *vector_queues; |
Laurent Vivier | a5ebce3 | 2022-08-11 08:24:39 -0400 | [diff] [blame] | 161 | QTAILQ_ENTRY(VirtIODevice) next; |
Alex Bennée | 661dee7 | 2023-07-10 16:35:08 +0100 | [diff] [blame] | 162 | /** |
| 163 | * @config_notifier: the event notifier that handles config events |
| 164 | */ |
Cindy Lu | 7d847d0 | 2022-12-22 15:04:47 +0800 | [diff] [blame] | 165 | EventNotifier config_notifier; |
Viktor Prutyanov | 206e91d | 2023-05-12 16:51:20 +0300 | [diff] [blame] | 166 | bool device_iotlb_enabled; |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 167 | }; |
| 168 | |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 169 | struct VirtioDeviceClass { |
Andreas Färber | 0ba94b6 | 2013-07-30 04:05:02 +0200 | [diff] [blame] | 170 | /*< private >*/ |
KONRAD Frederic | 8e05db9 | 2013-01-15 00:08:02 +0100 | [diff] [blame] | 171 | DeviceClass parent; |
Andreas Färber | 0ba94b6 | 2013-07-30 04:05:02 +0200 | [diff] [blame] | 172 | /*< public >*/ |
Andreas Färber | 1d244b4 | 2013-07-30 00:50:27 +0200 | [diff] [blame] | 173 | |
| 174 | /* This is what a VirtioDevice must implement */ |
Andreas Färber | 1d244b4 | 2013-07-30 00:50:27 +0200 | [diff] [blame] | 175 | DeviceRealize realize; |
Andreas Färber | 306ec6c | 2013-07-30 03:50:44 +0200 | [diff] [blame] | 176 | DeviceUnrealize unrealize; |
Jason Wang | 9d5b731 | 2015-07-27 17:49:19 +0800 | [diff] [blame] | 177 | uint64_t (*get_features)(VirtIODevice *vdev, |
| 178 | uint64_t requested_features, |
| 179 | Error **errp); |
Gerd Hoffmann | 019a3ed | 2015-06-01 10:45:40 +0200 | [diff] [blame] | 180 | uint64_t (*bad_features)(VirtIODevice *vdev); |
Gerd Hoffmann | d5aaa1b | 2015-06-03 14:47:19 +0200 | [diff] [blame] | 181 | void (*set_features)(VirtIODevice *vdev, uint64_t val); |
Cornelia Huck | 0b352fd | 2015-06-04 12:34:15 +0200 | [diff] [blame] | 182 | int (*validate_features)(VirtIODevice *vdev); |
KONRAD Frederic | 8e05db9 | 2013-01-15 00:08:02 +0100 | [diff] [blame] | 183 | void (*get_config)(VirtIODevice *vdev, uint8_t *config); |
| 184 | void (*set_config)(VirtIODevice *vdev, const uint8_t *config); |
| 185 | void (*reset)(VirtIODevice *vdev); |
| 186 | void (*set_status)(VirtIODevice *vdev, uint8_t val); |
Xuan Zhuo | f47af0a | 2022-11-10 17:57:39 +0800 | [diff] [blame] | 187 | /* Device must validate queue_index. */ |
Xuan Zhuo | b3a8d6f | 2022-10-17 17:25:45 +0800 | [diff] [blame] | 188 | void (*queue_reset)(VirtIODevice *vdev, uint32_t queue_index); |
Xuan Zhuo | f47af0a | 2022-11-10 17:57:39 +0800 | [diff] [blame] | 189 | /* Device must validate queue_index. */ |
Kangjie Xu | 3c37f8b | 2022-10-17 17:25:46 +0800 | [diff] [blame] | 190 | void (*queue_enable)(VirtIODevice *vdev, uint32_t queue_index); |
Michael S. Tsirkin | 9b706db | 2016-11-04 12:04:23 +0200 | [diff] [blame] | 191 | /* For transitional devices, this is a bitmap of features |
| 192 | * that are only exposed on the legacy interface but not |
| 193 | * the modern one. |
| 194 | */ |
| 195 | uint64_t legacy_features; |
KONRAD Frederic | 6a87acf | 2013-04-11 16:29:56 +0200 | [diff] [blame] | 196 | /* Test and clear event pending status. |
| 197 | * Should be called after unmask to avoid losing events. |
| 198 | * If backend does not support masking, |
| 199 | * must check in frontend instead. |
| 200 | */ |
| 201 | bool (*guest_notifier_pending)(VirtIODevice *vdev, int n); |
| 202 | /* Mask/unmask events from this vq. Any events reported |
| 203 | * while masked will become pending. |
| 204 | * If backend does not support masking, |
| 205 | * must mask in frontend instead. |
| 206 | */ |
| 207 | void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask); |
Paolo Bonzini | ff4c07d | 2016-10-21 22:48:07 +0200 | [diff] [blame] | 208 | int (*start_ioeventfd)(VirtIODevice *vdev); |
| 209 | void (*stop_ioeventfd)(VirtIODevice *vdev); |
Dr. David Alan Gilbert | ea43e25 | 2016-10-27 18:36:36 +0100 | [diff] [blame] | 210 | /* Saving and loading of a device; trying to deprecate save/load |
| 211 | * use vmsd for new devices. |
| 212 | */ |
Greg Kurz | 1b5fc0d | 2014-06-24 19:15:31 +0200 | [diff] [blame] | 213 | void (*save)(VirtIODevice *vdev, QEMUFile *f); |
| 214 | int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id); |
Michael S. Tsirkin | 1dd7138 | 2019-10-11 15:58:03 +0200 | [diff] [blame] | 215 | /* Post load hook in vmsd is called early while device is processed, and |
| 216 | * when VirtIODevice isn't fully initialized. Devices should use this instead, |
| 217 | * unless they specifically want to verify the migration stream as it's |
| 218 | * processed, e.g. for bounds checking. |
| 219 | */ |
| 220 | int (*post_load)(VirtIODevice *vdev); |
Dr. David Alan Gilbert | ea43e25 | 2016-10-27 18:36:36 +0100 | [diff] [blame] | 221 | const VMStateDescription *vmsd; |
Jens Freimann | 9711cd0 | 2019-10-29 12:49:04 +0100 | [diff] [blame] | 222 | bool (*primary_unplug_pending)(void *opaque); |
Jonah Palmer | c255488 | 2022-04-01 09:23:19 -0400 | [diff] [blame] | 223 | struct vhost_dev *(*get_vhost)(VirtIODevice *vdev); |
Viktor Prutyanov | 206e91d | 2023-05-12 16:51:20 +0300 | [diff] [blame] | 224 | void (*toggle_device_iotlb)(VirtIODevice *vdev); |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 225 | }; |
KONRAD Frederic | 8e05db9 | 2013-01-15 00:08:02 +0100 | [diff] [blame] | 226 | |
Gonglei | c8075ca | 2014-09-30 14:10:38 +0800 | [diff] [blame] | 227 | void virtio_instance_init_common(Object *proxy_obj, void *data, |
| 228 | size_t vdev_size, const char *vdev_name); |
| 229 | |
Alex Bennée | 3b6256c | 2023-07-10 16:35:07 +0100 | [diff] [blame] | 230 | /** |
| 231 | * virtio_init() - initialise the common VirtIODevice structure |
| 232 | * @vdev: pointer to VirtIODevice |
| 233 | * @device_id: the VirtIO device ID (see virtio_ids.h) |
| 234 | * @config_size: size of the config space |
| 235 | */ |
Jonah Palmer | 3857cd5 | 2022-04-01 09:23:18 -0400 | [diff] [blame] | 236 | void virtio_init(VirtIODevice *vdev, uint16_t device_id, size_t config_size); |
| 237 | |
KONRAD Frederic | 6a1a8cc | 2013-04-24 10:21:22 +0200 | [diff] [blame] | 238 | void virtio_cleanup(VirtIODevice *vdev); |
KONRAD Frederic | 8e05db9 | 2013-01-15 00:08:02 +0100 | [diff] [blame] | 239 | |
Marc-André Lureau | 9edc631 | 2022-02-20 20:39:25 +0400 | [diff] [blame] | 240 | void virtio_error(VirtIODevice *vdev, const char *fmt, ...) G_GNUC_PRINTF(2, 3); |
Stefan Hajnoczi | f5ed366 | 2016-09-21 16:52:19 +0100 | [diff] [blame] | 241 | |
KONRAD Frederic | 1034e9c | 2013-04-30 16:08:48 +0200 | [diff] [blame] | 242 | /* Set the child bus name. */ |
| 243 | void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name); |
| 244 | |
Fam Zheng | bf1780b | 2016-07-13 13:09:43 +0800 | [diff] [blame] | 245 | typedef void (*VirtIOHandleOutput)(VirtIODevice *, VirtQueue *); |
| 246 | |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 247 | VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, |
Fam Zheng | bf1780b | 2016-07-13 13:09:43 +0800 | [diff] [blame] | 248 | VirtIOHandleOutput handle_output); |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 249 | |
Jason Wang | f23fd81 | 2013-01-30 19:12:36 +0800 | [diff] [blame] | 250 | void virtio_del_queue(VirtIODevice *vdev, int n); |
| 251 | |
Michael S. Tsirkin | 722f8c5 | 2019-12-09 11:46:13 -0500 | [diff] [blame] | 252 | void virtio_delete_queue(VirtQueue *vq); |
| 253 | |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 254 | void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, |
| 255 | unsigned int len); |
| 256 | void virtqueue_flush(VirtQueue *vq, unsigned int count); |
Stefan Hajnoczi | 2640d2a | 2016-09-19 14:28:03 +0100 | [diff] [blame] | 257 | void virtqueue_detach_element(VirtQueue *vq, const VirtQueueElement *elem, |
| 258 | unsigned int len); |
Ladi Prosek | 27e57ef | 2016-11-03 09:55:49 +0100 | [diff] [blame] | 259 | void virtqueue_unpop(VirtQueue *vq, const VirtQueueElement *elem, |
| 260 | unsigned int len); |
Stefan Hajnoczi | 297a75e | 2016-09-07 17:20:48 +0200 | [diff] [blame] | 261 | bool virtqueue_rewind(VirtQueue *vq, unsigned int num); |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 262 | void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, |
| 263 | unsigned int len, unsigned int idx); |
| 264 | |
Jason Wang | 8607f5c | 2016-12-30 18:09:10 +0800 | [diff] [blame] | 265 | void virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem); |
Paolo Bonzini | 51b19eb | 2016-02-04 16:26:51 +0200 | [diff] [blame] | 266 | void *virtqueue_pop(VirtQueue *vq, size_t sz); |
Yuri Benditovich | 54e1770 | 2016-12-13 10:12:07 +0200 | [diff] [blame] | 267 | unsigned int virtqueue_drop_all(VirtQueue *vq); |
Jason Wang | 8607f5c | 2016-12-30 18:09:10 +0800 | [diff] [blame] | 268 | void *qemu_get_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, size_t sz); |
Jason Wang | 86044b2 | 2019-10-25 10:35:24 +0200 | [diff] [blame] | 269 | void qemu_put_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, |
| 270 | VirtQueueElement *elem); |
Amit Shah | 0d8d769 | 2012-09-25 00:05:15 +0530 | [diff] [blame] | 271 | int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, |
| 272 | unsigned int out_bytes); |
| 273 | void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, |
Michael S. Tsirkin | e1f7b48 | 2012-11-30 00:02:56 +0200 | [diff] [blame] | 274 | unsigned int *out_bytes, |
| 275 | unsigned max_in_bytes, unsigned max_out_bytes); |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 276 | |
Paolo Bonzini | 83d768b | 2016-11-18 16:07:02 +0100 | [diff] [blame] | 277 | void virtio_notify_irqfd(VirtIODevice *vdev, VirtQueue *vq); |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 278 | void virtio_notify(VirtIODevice *vdev, VirtQueue *vq); |
| 279 | |
Dr. David Alan Gilbert | 2f168d0 | 2017-09-25 12:29:17 +0100 | [diff] [blame] | 280 | int virtio_save(VirtIODevice *vdev, QEMUFile *f); |
Dr. David Alan Gilbert | 5943124 | 2016-07-14 18:22:45 +0100 | [diff] [blame] | 281 | |
Halil Pasic | 1a66585 | 2016-10-06 14:55:39 +0200 | [diff] [blame] | 282 | extern const VMStateInfo virtio_vmstate_info; |
| 283 | |
Halil Pasic | 1a66585 | 2016-10-06 14:55:39 +0200 | [diff] [blame] | 284 | #define VMSTATE_VIRTIO_DEVICE \ |
| 285 | { \ |
| 286 | .name = "virtio", \ |
| 287 | .info = &virtio_vmstate_info, \ |
| 288 | .flags = VMS_SINGLE, \ |
| 289 | } |
| 290 | |
Greg Kurz | 1b5fc0d | 2014-06-24 19:15:31 +0200 | [diff] [blame] | 291 | int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id); |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 292 | |
Alex Bennée | a0cc767 | 2023-07-10 16:35:06 +0100 | [diff] [blame] | 293 | /** |
| 294 | * virtio_notify_config() - signal a change to device config |
| 295 | * @vdev: the virtio device |
| 296 | * |
| 297 | * Assuming the virtio device is up (VIRTIO_CONFIG_S_DRIVER_OK) this |
| 298 | * will trigger a guest interrupt and update the config version. |
| 299 | */ |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 300 | void virtio_notify_config(VirtIODevice *vdev); |
| 301 | |
Stefan Hajnoczi | d0435bc | 2019-12-09 21:09:57 +0000 | [diff] [blame] | 302 | bool virtio_queue_get_notification(VirtQueue *vq); |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 303 | void virtio_queue_set_notification(VirtQueue *vq, int enable); |
| 304 | |
| 305 | int virtio_queue_ready(VirtQueue *vq); |
| 306 | |
| 307 | int virtio_queue_empty(VirtQueue *vq); |
| 308 | |
Paul Brook | 53c25ce | 2009-05-18 14:51:59 +0100 | [diff] [blame] | 309 | /* Host binding interface. */ |
| 310 | |
Paul Brook | 53c25ce | 2009-05-18 14:51:59 +0100 | [diff] [blame] | 311 | uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr); |
| 312 | uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr); |
| 313 | uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr); |
| 314 | void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data); |
| 315 | void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data); |
| 316 | void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data); |
Michael S. Tsirkin | adfb743 | 2015-06-04 12:34:24 +0200 | [diff] [blame] | 317 | uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr); |
| 318 | uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr); |
| 319 | uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr); |
| 320 | void virtio_config_modern_writeb(VirtIODevice *vdev, |
| 321 | uint32_t addr, uint32_t data); |
| 322 | void virtio_config_modern_writew(VirtIODevice *vdev, |
| 323 | uint32_t addr, uint32_t data); |
| 324 | void virtio_config_modern_writel(VirtIODevice *vdev, |
| 325 | uint32_t addr, uint32_t data); |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 326 | void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr); |
| 327 | hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n); |
Peter Maydell | e63c0ba | 2013-07-16 13:25:07 +0100 | [diff] [blame] | 328 | void virtio_queue_set_num(VirtIODevice *vdev, int n, int num); |
Paul Brook | 53c25ce | 2009-05-18 14:51:59 +0100 | [diff] [blame] | 329 | int virtio_queue_get_num(VirtIODevice *vdev, int n); |
Michael S. Tsirkin | 8c797e7 | 2017-01-12 23:26:22 +0200 | [diff] [blame] | 330 | int virtio_queue_get_max_num(VirtIODevice *vdev, int n); |
Jason Wang | 8ad176a | 2015-05-29 14:15:26 +0800 | [diff] [blame] | 331 | int virtio_get_num_queues(VirtIODevice *vdev); |
Cornelia Huck | ab223c9 | 2015-06-04 12:34:12 +0200 | [diff] [blame] | 332 | void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc, |
| 333 | hwaddr avail, hwaddr used); |
| 334 | void virtio_queue_update_rings(VirtIODevice *vdev, int n); |
Carlos López | f0d634e | 2023-03-17 01:27:51 +0100 | [diff] [blame] | 335 | void virtio_init_region_cache(VirtIODevice *vdev, int n); |
Peter Maydell | 6ce69d1 | 2013-07-16 13:25:08 +0100 | [diff] [blame] | 336 | void virtio_queue_set_align(VirtIODevice *vdev, int n, int align); |
Paul Brook | 53c25ce | 2009-05-18 14:51:59 +0100 | [diff] [blame] | 337 | void virtio_queue_notify(VirtIODevice *vdev, int n); |
Michael S. Tsirkin | 7055e68 | 2009-06-21 19:50:13 +0300 | [diff] [blame] | 338 | uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); |
| 339 | void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); |
Tiwei Bie | 6f80e61 | 2018-04-12 23:12:30 +0800 | [diff] [blame] | 340 | int virtio_queue_set_host_notifier_mr(VirtIODevice *vdev, int n, |
| 341 | MemoryRegion *mr, bool assign); |
Cornelia Huck | 0b352fd | 2015-06-04 12:34:15 +0200 | [diff] [blame] | 342 | int virtio_set_status(VirtIODevice *vdev, uint8_t val); |
Paul Brook | 53c25ce | 2009-05-18 14:51:59 +0100 | [diff] [blame] | 343 | void virtio_reset(void *opaque); |
Xuan Zhuo | b3a8d6f | 2022-10-17 17:25:45 +0800 | [diff] [blame] | 344 | void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index); |
Kangjie Xu | 3c37f8b | 2022-10-17 17:25:46 +0800 | [diff] [blame] | 345 | void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index); |
Paul Brook | 53c25ce | 2009-05-18 14:51:59 +0100 | [diff] [blame] | 346 | void virtio_update_irq(VirtIODevice *vdev); |
Gerd Hoffmann | d5aaa1b | 2015-06-03 14:47:19 +0200 | [diff] [blame] | 347 | int virtio_set_features(VirtIODevice *vdev, uint64_t val); |
Paul Brook | 53c25ce | 2009-05-18 14:51:59 +0100 | [diff] [blame] | 348 | |
Paul Brook | 53c25ce | 2009-05-18 14:51:59 +0100 | [diff] [blame] | 349 | /* Base devices. */ |
Paolo Bonzini | 12c5674 | 2012-05-16 12:54:05 +0200 | [diff] [blame] | 350 | typedef struct VirtIOBlkConf VirtIOBlkConf; |
Alex Williamson | f0c07c7 | 2010-09-02 09:00:50 -0600 | [diff] [blame] | 351 | struct virtio_net_conf; |
Amit Shah | 6b331ef | 2011-02-03 11:22:32 +0530 | [diff] [blame] | 352 | typedef struct virtio_serial_conf virtio_serial_conf; |
Gerd Hoffmann | f73ddba | 2014-03-14 14:39:20 +0100 | [diff] [blame] | 353 | typedef struct virtio_input_conf virtio_input_conf; |
Stefan Hajnoczi | 973abc7 | 2011-02-11 08:40:59 +0000 | [diff] [blame] | 354 | typedef struct VirtIOSCSIConf VirtIOSCSIConf; |
Amit Shah | 16c915b | 2012-06-20 12:29:32 +0530 | [diff] [blame] | 355 | typedef struct VirtIORNGConf VirtIORNGConf; |
Gerd Hoffmann | 97b1562 | 2009-10-21 15:25:35 +0200 | [diff] [blame] | 356 | |
Michael S. Tsirkin | 8172539 | 2010-01-10 13:52:53 +0200 | [diff] [blame] | 357 | #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \ |
Gerd Hoffmann | 019a3ed | 2015-06-01 10:45:40 +0200 | [diff] [blame] | 358 | DEFINE_PROP_BIT64("indirect_desc", _state, _field, \ |
| 359 | VIRTIO_RING_F_INDIRECT_DESC, true), \ |
| 360 | DEFINE_PROP_BIT64("event_idx", _state, _field, \ |
| 361 | VIRTIO_RING_F_EVENT_IDX, true), \ |
| 362 | DEFINE_PROP_BIT64("notify_on_empty", _state, _field, \ |
Michael S. Tsirkin | 09999a5 | 2015-07-22 12:32:25 +0300 | [diff] [blame] | 363 | VIRTIO_F_NOTIFY_ON_EMPTY, true), \ |
| 364 | DEFINE_PROP_BIT64("any_layout", _state, _field, \ |
Jason Wang | 8607f5c | 2016-12-30 18:09:10 +0800 | [diff] [blame] | 365 | VIRTIO_F_ANY_LAYOUT, true), \ |
| 366 | DEFINE_PROP_BIT64("iommu_platform", _state, _field, \ |
Jason Wang | 74b3e46 | 2019-10-25 10:35:27 +0200 | [diff] [blame] | 367 | VIRTIO_F_IOMMU_PLATFORM, false), \ |
| 368 | DEFINE_PROP_BIT64("packed", _state, _field, \ |
Kangjie Xu | 69e1c14 | 2022-10-17 17:25:47 +0800 | [diff] [blame] | 369 | VIRTIO_F_RING_PACKED, false), \ |
| 370 | DEFINE_PROP_BIT64("queue_reset", _state, _field, \ |
| 371 | VIRTIO_F_RING_RESET, true) |
Michael S. Tsirkin | 8172539 | 2010-01-10 13:52:53 +0200 | [diff] [blame] | 372 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 373 | hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n); |
Laurent Vivier | 0c9753e | 2020-07-27 17:33:19 +0200 | [diff] [blame] | 374 | bool virtio_queue_enabled_legacy(VirtIODevice *vdev, int n); |
Jason Wang | 23bfaf7 | 2019-03-25 11:40:36 +0800 | [diff] [blame] | 375 | bool virtio_queue_enabled(VirtIODevice *vdev, int n); |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 376 | hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n); |
| 377 | hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n); |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 378 | hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n); |
| 379 | hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n); |
| 380 | hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n); |
Jason Wang | 86044b2 | 2019-10-25 10:35:24 +0200 | [diff] [blame] | 381 | unsigned int virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n); |
| 382 | void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, |
| 383 | unsigned int idx); |
Maxime Coquelin | 2d4ba6c | 2017-11-16 19:48:34 +0100 | [diff] [blame] | 384 | void virtio_queue_restore_last_avail_idx(VirtIODevice *vdev, int n); |
Stefan Hajnoczi | 6793dfd | 2013-08-12 11:08:09 +0200 | [diff] [blame] | 385 | void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n); |
Yuri Benditovich | 312d3b3 | 2016-12-13 10:12:05 +0200 | [diff] [blame] | 386 | void virtio_queue_update_used_idx(VirtIODevice *vdev, int n); |
Michael S. Tsirkin | 1cbdabe | 2010-03-17 13:08:02 +0200 | [diff] [blame] | 387 | VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n); |
Jason Wang | e78a2b4 | 2013-01-30 19:12:37 +0800 | [diff] [blame] | 388 | uint16_t virtio_get_queue_index(VirtQueue *vq); |
Michael S. Tsirkin | 1cbdabe | 2010-03-17 13:08:02 +0200 | [diff] [blame] | 389 | EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq); |
Paolo Bonzini | 15b2bd1 | 2012-07-05 17:16:30 +0200 | [diff] [blame] | 390 | void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, |
| 391 | bool with_irqfd); |
Paolo Bonzini | ff4c07d | 2016-10-21 22:48:07 +0200 | [diff] [blame] | 392 | int virtio_device_start_ioeventfd(VirtIODevice *vdev); |
Paolo Bonzini | 310837d | 2016-11-18 16:07:00 +0100 | [diff] [blame] | 393 | int virtio_device_grab_ioeventfd(VirtIODevice *vdev); |
| 394 | void virtio_device_release_ioeventfd(VirtIODevice *vdev); |
Paolo Bonzini | 8e93cef | 2016-10-21 22:48:08 +0200 | [diff] [blame] | 395 | bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev); |
Michael S. Tsirkin | 1cbdabe | 2010-03-17 13:08:02 +0200 | [diff] [blame] | 396 | EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq); |
Stefan Hajnoczi | fcccb27 | 2019-11-05 15:09:46 +0100 | [diff] [blame] | 397 | void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled); |
Paolo Bonzini | fa283a4 | 2016-10-21 22:48:15 +0200 | [diff] [blame] | 398 | void virtio_queue_host_notifier_read(EventNotifier *n); |
Stefan Hajnoczi | db608fb | 2021-12-07 13:23:36 +0000 | [diff] [blame] | 399 | void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx); |
Stefan Hajnoczi | 38738f7 | 2022-04-27 15:35:37 +0100 | [diff] [blame] | 400 | void virtio_queue_aio_attach_host_notifier_no_poll(VirtQueue *vq, AioContext *ctx); |
Stefan Hajnoczi | db608fb | 2021-12-07 13:23:36 +0000 | [diff] [blame] | 401 | void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx); |
Jason Wang | e0d686b | 2015-04-23 14:21:46 +0800 | [diff] [blame] | 402 | VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector); |
| 403 | VirtQueue *virtio_vector_next_queue(VirtQueue *vq); |
Cindy Lu | 7d847d0 | 2022-12-22 15:04:47 +0800 | [diff] [blame] | 404 | EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev); |
| 405 | void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, |
| 406 | bool assign, bool with_irqfd); |
Greg Kurz | 98ed8ec | 2014-06-24 19:26:29 +0200 | [diff] [blame] | 407 | |
Gerd Hoffmann | 019a3ed | 2015-06-01 10:45:40 +0200 | [diff] [blame] | 408 | static inline void virtio_add_feature(uint64_t *features, unsigned int fbit) |
Cornelia Huck | 0cd09c3 | 2014-12-11 14:25:05 +0100 | [diff] [blame] | 409 | { |
Gerd Hoffmann | 019a3ed | 2015-06-01 10:45:40 +0200 | [diff] [blame] | 410 | assert(fbit < 64); |
Gerd Hoffmann | d5aaa1b | 2015-06-03 14:47:19 +0200 | [diff] [blame] | 411 | *features |= (1ULL << fbit); |
Cornelia Huck | 0cd09c3 | 2014-12-11 14:25:05 +0100 | [diff] [blame] | 412 | } |
| 413 | |
Gerd Hoffmann | 019a3ed | 2015-06-01 10:45:40 +0200 | [diff] [blame] | 414 | static inline void virtio_clear_feature(uint64_t *features, unsigned int fbit) |
Cornelia Huck | 0cd09c3 | 2014-12-11 14:25:05 +0100 | [diff] [blame] | 415 | { |
Gerd Hoffmann | 019a3ed | 2015-06-01 10:45:40 +0200 | [diff] [blame] | 416 | assert(fbit < 64); |
Gerd Hoffmann | d5aaa1b | 2015-06-03 14:47:19 +0200 | [diff] [blame] | 417 | *features &= ~(1ULL << fbit); |
Cornelia Huck | 0cd09c3 | 2014-12-11 14:25:05 +0100 | [diff] [blame] | 418 | } |
| 419 | |
Cornelia Huck | 95129d6 | 2015-08-17 11:48:29 +0200 | [diff] [blame] | 420 | static inline bool virtio_has_feature(uint64_t features, unsigned int fbit) |
Cornelia Huck | ef546f1 | 2014-12-11 14:25:06 +0100 | [diff] [blame] | 421 | { |
Gerd Hoffmann | 019a3ed | 2015-06-01 10:45:40 +0200 | [diff] [blame] | 422 | assert(fbit < 64); |
Gerd Hoffmann | d5aaa1b | 2015-06-03 14:47:19 +0200 | [diff] [blame] | 423 | return !!(features & (1ULL << fbit)); |
Cornelia Huck | ef546f1 | 2014-12-11 14:25:06 +0100 | [diff] [blame] | 424 | } |
| 425 | |
Hawkins Jiawei | 0a47810 | 2023-06-02 19:52:13 +0800 | [diff] [blame] | 426 | static inline bool virtio_vdev_has_feature(const VirtIODevice *vdev, |
Cornelia Huck | 95129d6 | 2015-08-17 11:48:29 +0200 | [diff] [blame] | 427 | unsigned int fbit) |
Cornelia Huck | ef546f1 | 2014-12-11 14:25:06 +0100 | [diff] [blame] | 428 | { |
Cornelia Huck | 95129d6 | 2015-08-17 11:48:29 +0200 | [diff] [blame] | 429 | return virtio_has_feature(vdev->guest_features, fbit); |
Cornelia Huck | ef546f1 | 2014-12-11 14:25:06 +0100 | [diff] [blame] | 430 | } |
| 431 | |
Jason Wang | 74aae7b | 2015-08-05 17:50:07 +0800 | [diff] [blame] | 432 | static inline bool virtio_host_has_feature(VirtIODevice *vdev, |
| 433 | unsigned int fbit) |
| 434 | { |
Cornelia Huck | 95129d6 | 2015-08-17 11:48:29 +0200 | [diff] [blame] | 435 | return virtio_has_feature(vdev->host_features, fbit); |
Jason Wang | 74aae7b | 2015-08-05 17:50:07 +0800 | [diff] [blame] | 436 | } |
| 437 | |
Greg Kurz | 616a655 | 2014-06-24 19:38:54 +0200 | [diff] [blame] | 438 | static inline bool virtio_is_big_endian(VirtIODevice *vdev) |
Greg Kurz | 98ed8ec | 2014-06-24 19:26:29 +0200 | [diff] [blame] | 439 | { |
Cornelia Huck | 95129d6 | 2015-08-17 11:48:29 +0200 | [diff] [blame] | 440 | if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { |
Cornelia Huck | 3c18559 | 2015-06-04 12:34:11 +0200 | [diff] [blame] | 441 | assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); |
| 442 | return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG; |
| 443 | } |
| 444 | /* Devices conforming to VIRTIO 1.0 or later are always LE. */ |
| 445 | return false; |
Greg Kurz | 98ed8ec | 2014-06-24 19:26:29 +0200 | [diff] [blame] | 446 | } |
Xie Yongji | e57f2c3 | 2019-06-26 10:31:26 +0800 | [diff] [blame] | 447 | |
Alex Bennée | 4987e5b | 2022-11-30 11:24:39 +0000 | [diff] [blame] | 448 | /** |
| 449 | * virtio_device_started() - check if device started |
| 450 | * @vdev - the VirtIO device |
| 451 | * @status - the devices status bits |
| 452 | * |
| 453 | * Check if the device is started. For most modern machines this is |
| 454 | * tracked via the @vdev->started field (to support migration), |
| 455 | * otherwise we check for the final negotiated status bit that |
| 456 | * indicates everything is ready. |
| 457 | */ |
Xie Yongji | e57f2c3 | 2019-06-26 10:31:26 +0800 | [diff] [blame] | 458 | static inline bool virtio_device_started(VirtIODevice *vdev, uint8_t status) |
| 459 | { |
| 460 | if (vdev->use_started) { |
| 461 | return vdev->started; |
| 462 | } |
| 463 | |
Alex Bennée | 259d69c | 2022-11-07 12:14:07 +0000 | [diff] [blame] | 464 | return status & VIRTIO_CONFIG_S_DRIVER_OK; |
| 465 | } |
| 466 | |
| 467 | /** |
| 468 | * virtio_device_should_start() - check if device startable |
| 469 | * @vdev - the VirtIO device |
| 470 | * @status - the devices status bits |
| 471 | * |
| 472 | * This is similar to virtio_device_started() but also encapsulates a |
| 473 | * check on the VM status which would prevent a device starting |
| 474 | * anyway. |
| 475 | */ |
| 476 | static inline bool virtio_device_should_start(VirtIODevice *vdev, uint8_t status) |
| 477 | { |
Alex Bennée | 9f6bcfd | 2022-08-02 10:49:58 +0100 | [diff] [blame] | 478 | if (!vdev->vm_running) { |
| 479 | return false; |
| 480 | } |
| 481 | |
Alex Bennée | 4987e5b | 2022-11-30 11:24:39 +0000 | [diff] [blame] | 482 | return virtio_device_started(vdev, status); |
Xie Yongji | e57f2c3 | 2019-06-26 10:31:26 +0800 | [diff] [blame] | 483 | } |
| 484 | |
| 485 | static inline void virtio_set_started(VirtIODevice *vdev, bool started) |
| 486 | { |
| 487 | if (started) { |
| 488 | vdev->start_on_kick = false; |
| 489 | } |
| 490 | |
| 491 | if (vdev->use_started) { |
| 492 | vdev->started = started; |
| 493 | } |
| 494 | } |
Michael Roth | 9d7bd08 | 2019-11-19 18:50:03 -0600 | [diff] [blame] | 495 | |
| 496 | static inline void virtio_set_disabled(VirtIODevice *vdev, bool disable) |
| 497 | { |
| 498 | if (vdev->use_disabled_flag) { |
| 499 | vdev->disabled = disable; |
| 500 | } |
| 501 | } |
| 502 | |
| 503 | static inline bool virtio_device_disabled(VirtIODevice *vdev) |
| 504 | { |
| 505 | return unlikely(vdev->disabled || vdev->broken); |
| 506 | } |
| 507 | |
Cornelia Huck | 7c78bdd | 2020-07-07 12:54:45 +0200 | [diff] [blame] | 508 | bool virtio_legacy_allowed(VirtIODevice *vdev); |
Stefano Garzarella | d55f518 | 2020-09-21 14:25:03 +0200 | [diff] [blame] | 509 | bool virtio_legacy_check_disabled(VirtIODevice *vdev); |
Cornelia Huck | 7c78bdd | 2020-07-07 12:54:45 +0200 | [diff] [blame] | 510 | |
aliguori | 967f97f | 2008-12-04 19:38:57 +0000 | [diff] [blame] | 511 | #endif |