virtio.c 49.8 KB
Newer Older
A
aliguori 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * Virtio Support
 *
 * Copyright IBM, Corp. 2007
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 *
 */

P
Peter Maydell 已提交
14
#include "qemu/osdep.h"
A
aliguori 已提交
15

16
#include "trace.h"
17
#include "exec/address-spaces.h"
18
#include "qemu/error-report.h"
P
Paolo Bonzini 已提交
19
#include "hw/virtio/virtio.h"
20
#include "qemu/atomic.h"
P
Paolo Bonzini 已提交
21
#include "hw/virtio/virtio-bus.h"
22
#include "migration/migration.h"
23
#include "hw/virtio/virtio-access.h"
A
aliguori 已提交
24

25 26 27 28 29
/*
 * The alignment to use between consumer and producer parts of vring.
 * x86 pagesize again. This is the default, used by transports like PCI
 * which don't provide a means for the guest to tell the host the alignment.
 */
30 31
#define VIRTIO_PCI_VRING_ALIGN         4096

A
aliguori 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
typedef struct VRingDesc
{
    uint64_t addr;
    uint32_t len;
    uint16_t flags;
    uint16_t next;
} VRingDesc;

typedef struct VRingAvail
{
    uint16_t flags;
    uint16_t idx;
    uint16_t ring[0];
} VRingAvail;

typedef struct VRingUsedElem
{
    uint32_t id;
    uint32_t len;
} VRingUsedElem;

typedef struct VRingUsed
{
    uint16_t flags;
    uint16_t idx;
    VRingUsedElem ring[0];
} VRingUsed;

typedef struct VRing
{
    unsigned int num;
C
Cornelia Huck 已提交
63
    unsigned int num_default;
64
    unsigned int align;
A
Avi Kivity 已提交
65 66 67
    hwaddr desc;
    hwaddr avail;
    hwaddr used;
A
aliguori 已提交
68 69 70 71 72 73
} VRing;

struct VirtQueue
{
    VRing vring;
    uint16_t last_avail_idx;
74 75 76

    uint16_t used_idx;

M
Michael S. Tsirkin 已提交
77 78 79 80 81 82 83 84 85
    /* Last used index value we have signalled on */
    uint16_t signalled_used;

    /* Last used index value we have signalled on */
    bool signalled_used_valid;

    /* Notification enabled? */
    bool notification;

86 87
    uint16_t queue_index;

A
aliguori 已提交
88
    int inuse;
M
Michael S. Tsirkin 已提交
89

90
    uint16_t vector;
A
aliguori 已提交
91
    void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
92 93 94
    VirtIODevice *vdev;
    EventNotifier guest_notifier;
    EventNotifier host_notifier;
95
    QLIST_ENTRY(VirtQueue) node;
A
aliguori 已提交
96 97 98
};

/* virt queue functions */
99
void virtio_queue_update_rings(VirtIODevice *vdev, int n)
A
aliguori 已提交
100
{
101
    VRing *vring = &vdev->vq[n].vring;
P
Paul Brook 已提交
102

103 104 105 106 107 108 109 110
    if (!vring->desc) {
        /* not yet setup -> nothing to do */
        return;
    }
    vring->avail = vring->desc + vring->num * sizeof(VRingDesc);
    vring->used = vring_align(vring->avail +
                              offsetof(VRingAvail, ring[vring->num]),
                              vring->align);
A
aliguori 已提交
111 112
}

113 114
static void vring_desc_read(VirtIODevice *vdev, VRingDesc *desc,
                            hwaddr desc_pa, int i)
A
aliguori 已提交
115
{
116 117 118 119 120 121
    address_space_read(&address_space_memory, desc_pa + i * sizeof(VRingDesc),
                       MEMTXATTRS_UNSPECIFIED, (void *)desc, sizeof(VRingDesc));
    virtio_tswap64s(vdev, &desc->addr);
    virtio_tswap32s(vdev, &desc->len);
    virtio_tswap16s(vdev, &desc->flags);
    virtio_tswap16s(vdev, &desc->next);
A
aliguori 已提交
122 123 124 125
}

static inline uint16_t vring_avail_flags(VirtQueue *vq)
{
A
Avi Kivity 已提交
126
    hwaddr pa;
A
aliguori 已提交
127
    pa = vq->vring.avail + offsetof(VRingAvail, flags);
128
    return virtio_lduw_phys(vq->vdev, pa);
A
aliguori 已提交
129 130 131 132
}

static inline uint16_t vring_avail_idx(VirtQueue *vq)
{
A
Avi Kivity 已提交
133
    hwaddr pa;
A
aliguori 已提交
134
    pa = vq->vring.avail + offsetof(VRingAvail, idx);
135
    return virtio_lduw_phys(vq->vdev, pa);
A
aliguori 已提交
136 137 138 139
}

static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)
{
A
Avi Kivity 已提交
140
    hwaddr pa;
A
aliguori 已提交
141
    pa = vq->vring.avail + offsetof(VRingAvail, ring[i]);
142
    return virtio_lduw_phys(vq->vdev, pa);
A
aliguori 已提交
143 144
}

145
static inline uint16_t vring_get_used_event(VirtQueue *vq)
M
Michael S. Tsirkin 已提交
146 147 148 149
{
    return vring_avail_ring(vq, vq->vring.num);
}

A
aliguori 已提交
150 151
static inline void vring_used_ring_id(VirtQueue *vq, int i, uint32_t val)
{
A
Avi Kivity 已提交
152
    hwaddr pa;
A
aliguori 已提交
153
    pa = vq->vring.used + offsetof(VRingUsed, ring[i].id);
154
    virtio_stl_phys(vq->vdev, pa, val);
A
aliguori 已提交
155 156 157 158
}

static inline void vring_used_ring_len(VirtQueue *vq, int i, uint32_t val)
{
A
Avi Kivity 已提交
159
    hwaddr pa;
A
aliguori 已提交
160
    pa = vq->vring.used + offsetof(VRingUsed, ring[i].len);
161
    virtio_stl_phys(vq->vdev, pa, val);
A
aliguori 已提交
162 163 164 165
}

static uint16_t vring_used_idx(VirtQueue *vq)
{
A
Avi Kivity 已提交
166
    hwaddr pa;
A
aliguori 已提交
167
    pa = vq->vring.used + offsetof(VRingUsed, idx);
168
    return virtio_lduw_phys(vq->vdev, pa);
A
aliguori 已提交
169 170
}

M
Michael S. Tsirkin 已提交
171
static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val)
A
aliguori 已提交
172
{
A
Avi Kivity 已提交
173
    hwaddr pa;
A
aliguori 已提交
174
    pa = vq->vring.used + offsetof(VRingUsed, idx);
175
    virtio_stw_phys(vq->vdev, pa, val);
176
    vq->used_idx = val;
A
aliguori 已提交
177 178 179 180
}

static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask)
{
181
    VirtIODevice *vdev = vq->vdev;
A
Avi Kivity 已提交
182
    hwaddr pa;
A
aliguori 已提交
183
    pa = vq->vring.used + offsetof(VRingUsed, flags);
184
    virtio_stw_phys(vdev, pa, virtio_lduw_phys(vdev, pa) | mask);
A
aliguori 已提交
185 186 187 188
}

static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask)
{
189
    VirtIODevice *vdev = vq->vdev;
A
Avi Kivity 已提交
190
    hwaddr pa;
A
aliguori 已提交
191
    pa = vq->vring.used + offsetof(VRingUsed, flags);
192
    virtio_stw_phys(vdev, pa, virtio_lduw_phys(vdev, pa) & ~mask);
A
aliguori 已提交
193 194
}

195
static inline void vring_set_avail_event(VirtQueue *vq, uint16_t val)
M
Michael S. Tsirkin 已提交
196
{
A
Avi Kivity 已提交
197
    hwaddr pa;
M
Michael S. Tsirkin 已提交
198 199 200 201
    if (!vq->notification) {
        return;
    }
    pa = vq->vring.used + offsetof(VRingUsed, ring[vq->vring.num]);
202
    virtio_stw_phys(vq->vdev, pa, val);
M
Michael S. Tsirkin 已提交
203 204
}

A
aliguori 已提交
205 206
void virtio_queue_set_notification(VirtQueue *vq, int enable)
{
M
Michael S. Tsirkin 已提交
207
    vq->notification = enable;
208
    if (virtio_vdev_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
209
        vring_set_avail_event(vq, vring_avail_idx(vq));
M
Michael S. Tsirkin 已提交
210
    } else if (enable) {
A
aliguori 已提交
211
        vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
M
Michael S. Tsirkin 已提交
212
    } else {
A
aliguori 已提交
213
        vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY);
M
Michael S. Tsirkin 已提交
214
    }
215 216 217 218
    if (enable) {
        /* Expose avail event/used flags before caller checks the avail idx. */
        smp_mb();
    }
A
aliguori 已提交
219 220 221 222 223 224 225 226 227 228 229 230
}

int virtio_queue_ready(VirtQueue *vq)
{
    return vq->vring.avail != 0;
}

int virtio_queue_empty(VirtQueue *vq)
{
    return vring_avail_idx(vq) == vq->last_avail_idx;
}

231 232
static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem,
                               unsigned int len)
A
aliguori 已提交
233 234 235 236 237 238 239 240
{
    unsigned int offset;
    int i;

    offset = 0;
    for (i = 0; i < elem->in_num; i++) {
        size_t size = MIN(len - offset, elem->in_sg[i].iov_len);

241 242 243
        cpu_physical_memory_unmap(elem->in_sg[i].iov_base,
                                  elem->in_sg[i].iov_len,
                                  1, size);
A
aliguori 已提交
244

245
        offset += size;
A
aliguori 已提交
246 247
    }

248 249 250 251
    for (i = 0; i < elem->out_num; i++)
        cpu_physical_memory_unmap(elem->out_sg[i].iov_base,
                                  elem->out_sg[i].iov_len,
                                  0, elem->out_sg[i].iov_len);
252 253
}

J
Jason Wang 已提交
254 255 256 257 258 259 260
void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem,
                       unsigned int len)
{
    vq->last_avail_idx--;
    virtqueue_unmap_sg(vq, elem, len);
}

261 262 263 264 265 266
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
                    unsigned int len, unsigned int idx)
{
    trace_virtqueue_fill(vq, elem, len, idx);

    virtqueue_unmap_sg(vq, elem, len);
267

268
    idx = (idx + vq->used_idx) % vq->vring.num;
A
aliguori 已提交
269 270 271 272 273 274 275 276

    /* Get a pointer to the next entry in the used ring. */
    vring_used_ring_id(vq, idx, elem->index);
    vring_used_ring_len(vq, idx, len);
}

void virtqueue_flush(VirtQueue *vq, unsigned int count)
{
M
Michael S. Tsirkin 已提交
277
    uint16_t old, new;
A
aliguori 已提交
278
    /* Make sure buffer is written before we update index. */
279
    smp_wmb();
280
    trace_virtqueue_flush(vq, count);
281
    old = vq->used_idx;
M
Michael S. Tsirkin 已提交
282 283
    new = old + count;
    vring_used_idx_set(vq, new);
A
aliguori 已提交
284
    vq->inuse -= count;
M
Michael S. Tsirkin 已提交
285 286
    if (unlikely((int16_t)(new - vq->signalled_used) < (uint16_t)(new - old)))
        vq->signalled_used_valid = false;
A
aliguori 已提交
287 288 289 290 291 292 293 294 295 296 297 298 299 300
}

void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
                    unsigned int len)
{
    virtqueue_fill(vq, elem, len, 0);
    virtqueue_flush(vq, 1);
}

static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
{
    uint16_t num_heads = vring_avail_idx(vq) - idx;

    /* Check it isn't doing very strange things with descriptor numbers. */
A
aliguori 已提交
301
    if (num_heads > vq->vring.num) {
302 303
        error_report("Guest moved used index from %u to %u",
                     idx, vring_avail_idx(vq));
A
aliguori 已提交
304 305
        exit(1);
    }
306 307 308 309 310
    /* On success, callers read a descriptor at vq->last_avail_idx.
     * Make sure descriptor read does not bypass avail index read. */
    if (num_heads) {
        smp_rmb();
    }
A
aliguori 已提交
311 312 313 314 315 316 317 318 319 320 321 322 323

    return num_heads;
}

static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
{
    unsigned int head;

    /* Grab the next descriptor number they're advertising, and increment
     * the index we've seen. */
    head = vring_avail_ring(vq, idx % vq->vring.num);

    /* If their number is silly, that's a fatal mistake. */
A
aliguori 已提交
324
    if (head >= vq->vring.num) {
325
        error_report("Guest says index %u is available", head);
A
aliguori 已提交
326 327
        exit(1);
    }
A
aliguori 已提交
328 329 330 331

    return head;
}

332 333
static unsigned virtqueue_read_next_desc(VirtIODevice *vdev, VRingDesc *desc,
                                         hwaddr desc_pa, unsigned int max)
A
aliguori 已提交
334 335 336 337
{
    unsigned int next;

    /* If this descriptor says it doesn't chain, we're done. */
338
    if (!(desc->flags & VRING_DESC_F_NEXT)) {
339
        return max;
340
    }
A
aliguori 已提交
341 342

    /* Check they're not leading us off end of descriptors. */
343
    next = desc->next;
A
aliguori 已提交
344
    /* Make sure compiler knows to grab that: we don't want it changing! */
345
    smp_wmb();
A
aliguori 已提交
346

347
    if (next >= max) {
348
        error_report("Desc next is %u", next);
A
aliguori 已提交
349 350
        exit(1);
    }
A
aliguori 已提交
351

352
    vring_desc_read(vdev, desc, desc_pa, next);
A
aliguori 已提交
353 354 355
    return next;
}

356
void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
357 358
                               unsigned int *out_bytes,
                               unsigned max_in_bytes, unsigned max_out_bytes)
A
aliguori 已提交
359
{
360
    unsigned int idx;
361
    unsigned int total_bufs, in_total, out_total;
A
aliguori 已提交
362 363 364

    idx = vq->last_avail_idx;

365
    total_bufs = in_total = out_total = 0;
A
aliguori 已提交
366
    while (virtqueue_num_heads(vq, idx)) {
367
        VirtIODevice *vdev = vq->vdev;
368
        unsigned int max, num_bufs, indirect = 0;
369
        VRingDesc desc;
A
Avi Kivity 已提交
370
        hwaddr desc_pa;
A
aliguori 已提交
371 372
        int i;

373 374
        max = vq->vring.num;
        num_bufs = total_bufs;
A
aliguori 已提交
375
        i = virtqueue_get_head(vq, idx++);
376
        desc_pa = vq->vring.desc;
377
        vring_desc_read(vdev, &desc, desc_pa, i);
378

379 380
        if (desc.flags & VRING_DESC_F_INDIRECT) {
            if (desc.len % sizeof(VRingDesc)) {
381
                error_report("Invalid size for indirect buffer table");
382 383 384 385 386
                exit(1);
            }

            /* If we've got too many, that implies a descriptor loop. */
            if (num_bufs >= max) {
387
                error_report("Looped descriptor");
388 389 390 391 392
                exit(1);
            }

            /* loop over the indirect descriptor table */
            indirect = 1;
393 394
            max = desc.len / sizeof(VRingDesc);
            desc_pa = desc.addr;
395
            num_bufs = i = 0;
396
            vring_desc_read(vdev, &desc, desc_pa, i);
397 398
        }

A
aliguori 已提交
399 400
        do {
            /* If we've got too many, that implies a descriptor loop. */
401
            if (++num_bufs > max) {
402
                error_report("Looped descriptor");
A
aliguori 已提交
403 404
                exit(1);
            }
A
aliguori 已提交
405

406 407
            if (desc.flags & VRING_DESC_F_WRITE) {
                in_total += desc.len;
A
aliguori 已提交
408
            } else {
409
                out_total += desc.len;
A
aliguori 已提交
410
            }
411 412 413
            if (in_total >= max_in_bytes && out_total >= max_out_bytes) {
                goto done;
            }
414
        } while ((i = virtqueue_read_next_desc(vdev, &desc, desc_pa, max)) != max);
415 416 417 418 419

        if (!indirect)
            total_bufs = num_bufs;
        else
            total_bufs++;
A
aliguori 已提交
420
    }
421
done:
422 423 424 425 426 427 428
    if (in_bytes) {
        *in_bytes = in_total;
    }
    if (out_bytes) {
        *out_bytes = out_total;
    }
}
A
aliguori 已提交
429

430 431 432 433 434
int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
                          unsigned int out_bytes)
{
    unsigned int in_total, out_total;

435 436
    virtqueue_get_avail_bytes(vq, &in_total, &out_total, in_bytes, out_bytes);
    return in_bytes <= in_total && out_bytes <= out_total;
A
aliguori 已提交
437 438
}

439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
static void virtqueue_map_desc(unsigned int *p_num_sg, hwaddr *addr, struct iovec *iov,
                               unsigned int max_num_sg, bool is_write,
                               hwaddr pa, size_t sz)
{
    unsigned num_sg = *p_num_sg;
    assert(num_sg <= max_num_sg);

    while (sz) {
        hwaddr len = sz;

        if (num_sg == max_num_sg) {
            error_report("virtio: too many write descriptors in indirect table");
            exit(1);
        }

        iov[num_sg].iov_base = cpu_physical_memory_map(pa, &len, is_write);
        iov[num_sg].iov_len = len;
        addr[num_sg] = pa;

        sz -= len;
        pa += len;
        num_sg++;
    }
    *p_num_sg = num_sg;
}

M
Michael S. Tsirkin 已提交
465 466 467
static void virtqueue_map_iovec(struct iovec *sg, hwaddr *addr,
                                unsigned int *num_sg, unsigned int max_size,
                                int is_write)
K
Kevin Wolf 已提交
468 469
{
    unsigned int i;
A
Avi Kivity 已提交
470
    hwaddr len;
K
Kevin Wolf 已提交
471

M
Michael S. Tsirkin 已提交
472 473 474 475 476 477 478 479 480 481 482 483 484
    /* Note: this function MUST validate input, some callers
     * are passing in num_sg values received over the network.
     */
    /* TODO: teach all callers that this can fail, and return failure instead
     * of asserting here.
     * When we do, we might be able to re-enable NDEBUG below.
     */
#ifdef NDEBUG
#error building with NDEBUG is not supported
#endif
    assert(*num_sg <= max_size);

    for (i = 0; i < *num_sg; i++) {
K
Kevin Wolf 已提交
485 486
        len = sg[i].iov_len;
        sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
M
Michael S. Tsirkin 已提交
487
        if (!sg[i].iov_base) {
M
Michael Tokarev 已提交
488
            error_report("virtio: error trying to map MMIO memory");
K
Kevin Wolf 已提交
489 490
            exit(1);
        }
491 492
        if (len != sg[i].iov_len) {
            error_report("virtio: unexpected memory split");
M
Michael S. Tsirkin 已提交
493 494
            exit(1);
        }
K
Kevin Wolf 已提交
495 496 497
    }
}

M
Michael S. Tsirkin 已提交
498 499 500
void virtqueue_map(VirtQueueElement *elem)
{
    virtqueue_map_iovec(elem->in_sg, elem->in_addr, &elem->in_num,
501
                        VIRTQUEUE_MAX_SIZE, 1);
M
Michael S. Tsirkin 已提交
502
    virtqueue_map_iovec(elem->out_sg, elem->out_addr, &elem->out_num,
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
                        VIRTQUEUE_MAX_SIZE, 0);
}

void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num)
{
    VirtQueueElement *elem;
    size_t in_addr_ofs = QEMU_ALIGN_UP(sz, __alignof__(elem->in_addr[0]));
    size_t out_addr_ofs = in_addr_ofs + in_num * sizeof(elem->in_addr[0]);
    size_t out_addr_end = out_addr_ofs + out_num * sizeof(elem->out_addr[0]);
    size_t in_sg_ofs = QEMU_ALIGN_UP(out_addr_end, __alignof__(elem->in_sg[0]));
    size_t out_sg_ofs = in_sg_ofs + in_num * sizeof(elem->in_sg[0]);
    size_t out_sg_end = out_sg_ofs + out_num * sizeof(elem->out_sg[0]);

    assert(sz >= sizeof(VirtQueueElement));
    elem = g_malloc(out_sg_end);
    elem->out_num = out_num;
    elem->in_num = in_num;
    elem->in_addr = (void *)elem + in_addr_ofs;
    elem->out_addr = (void *)elem + out_addr_ofs;
    elem->in_sg = (void *)elem + in_sg_ofs;
    elem->out_sg = (void *)elem + out_sg_ofs;
    return elem;
M
Michael S. Tsirkin 已提交
525 526
}

527
void *virtqueue_pop(VirtQueue *vq, size_t sz)
A
aliguori 已提交
528
{
529
    unsigned int i, head, max;
A
Avi Kivity 已提交
530
    hwaddr desc_pa = vq->vring.desc;
531
    VirtIODevice *vdev = vq->vdev;
532
    VirtQueueElement *elem;
533 534 535
    unsigned out_num, in_num;
    hwaddr addr[VIRTQUEUE_MAX_SIZE];
    struct iovec iov[VIRTQUEUE_MAX_SIZE];
536
    VRingDesc desc;
A
aliguori 已提交
537

538 539 540
    if (!virtqueue_num_heads(vq, vq->last_avail_idx)) {
        return NULL;
    }
A
aliguori 已提交
541 542

    /* When we start there are none of either input nor output. */
543
    out_num = in_num = 0;
A
aliguori 已提交
544

545 546
    max = vq->vring.num;

A
aliguori 已提交
547
    i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
548
    if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
549
        vring_set_avail_event(vq, vq->last_avail_idx);
M
Michael S. Tsirkin 已提交
550
    }
551

552 553 554
    vring_desc_read(vdev, &desc, desc_pa, i);
    if (desc.flags & VRING_DESC_F_INDIRECT) {
        if (desc.len % sizeof(VRingDesc)) {
555
            error_report("Invalid size for indirect buffer table");
556 557 558 559
            exit(1);
        }

        /* loop over the indirect descriptor table */
560 561
        max = desc.len / sizeof(VRingDesc);
        desc_pa = desc.addr;
562
        i = 0;
563
        vring_desc_read(vdev, &desc, desc_pa, i);
564 565
    }

K
Kevin Wolf 已提交
566
    /* Collect all the descriptors */
A
aliguori 已提交
567
    do {
568
        if (desc.flags & VRING_DESC_F_WRITE) {
569
            virtqueue_map_desc(&in_num, addr + out_num, iov + out_num,
570
                               VIRTQUEUE_MAX_SIZE - out_num, true, desc.addr, desc.len);
K
Kevin Wolf 已提交
571
        } else {
572 573
            if (in_num) {
                error_report("Incorrect order for descriptors");
574 575
                exit(1);
            }
576
            virtqueue_map_desc(&out_num, addr, iov,
577
                               VIRTQUEUE_MAX_SIZE, false, desc.addr, desc.len);
K
Kevin Wolf 已提交
578
        }
A
aliguori 已提交
579 580

        /* If we've got too many, that implies a descriptor loop. */
581
        if ((in_num + out_num) > max) {
582
            error_report("Looped descriptor");
A
aliguori 已提交
583 584
            exit(1);
        }
585
    } while ((i = virtqueue_read_next_desc(vdev, &desc, desc_pa, max)) != max);
A
aliguori 已提交
586

587 588
    /* Now copy what we have collected and mapped */
    elem = virtqueue_alloc_element(sz, out_num, in_num);
A
aliguori 已提交
589
    elem->index = head;
590 591 592 593 594 595 596 597
    for (i = 0; i < out_num; i++) {
        elem->out_addr[i] = addr[i];
        elem->out_sg[i] = iov[i];
    }
    for (i = 0; i < in_num; i++) {
        elem->in_addr[i] = addr[out_num + i];
        elem->in_sg[i] = iov[out_num + i];
    }
A
aliguori 已提交
598 599 600

    vq->inuse++;

601
    trace_virtqueue_pop(vq, elem, elem->in_num, elem->out_num);
602
    return elem;
A
aliguori 已提交
603 604
}

605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
/* Reading and writing a structure directly to QEMUFile is *awful*, but
 * it is what QEMU has always done by mistake.  We can change it sooner
 * or later by bumping the version number of the affected vm states.
 * In the meanwhile, since the in-memory layout of VirtQueueElement
 * has changed, we need to marshal to and from the layout that was
 * used before the change.
 */
typedef struct VirtQueueElementOld {
    unsigned int index;
    unsigned int out_num;
    unsigned int in_num;
    hwaddr in_addr[VIRTQUEUE_MAX_SIZE];
    hwaddr out_addr[VIRTQUEUE_MAX_SIZE];
    struct iovec in_sg[VIRTQUEUE_MAX_SIZE];
    struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
} VirtQueueElementOld;

622 623
void *qemu_get_virtqueue_element(QEMUFile *f, size_t sz)
{
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
    VirtQueueElement *elem;
    VirtQueueElementOld data;
    int i;

    qemu_get_buffer(f, (uint8_t *)&data, sizeof(VirtQueueElementOld));

    elem = virtqueue_alloc_element(sz, data.out_num, data.in_num);
    elem->index = data.index;

    for (i = 0; i < elem->in_num; i++) {
        elem->in_addr[i] = data.in_addr[i];
    }

    for (i = 0; i < elem->out_num; i++) {
        elem->out_addr[i] = data.out_addr[i];
    }

    for (i = 0; i < elem->in_num; i++) {
        /* Base is overwritten by virtqueue_map.  */
        elem->in_sg[i].iov_base = 0;
        elem->in_sg[i].iov_len = data.in_sg[i].iov_len;
    }

    for (i = 0; i < elem->out_num; i++) {
        /* Base is overwritten by virtqueue_map.  */
        elem->out_sg[i].iov_base = 0;
        elem->out_sg[i].iov_len = data.out_sg[i].iov_len;
    }

653 654 655 656 657 658
    virtqueue_map(elem);
    return elem;
}

void qemu_put_virtqueue_element(QEMUFile *f, VirtQueueElement *elem)
{
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
    VirtQueueElementOld data;
    int i;

    memset(&data, 0, sizeof(data));
    data.index = elem->index;
    data.in_num = elem->in_num;
    data.out_num = elem->out_num;

    for (i = 0; i < elem->in_num; i++) {
        data.in_addr[i] = elem->in_addr[i];
    }

    for (i = 0; i < elem->out_num; i++) {
        data.out_addr[i] = elem->out_addr[i];
    }

    for (i = 0; i < elem->in_num; i++) {
        /* Base is overwritten by virtqueue_map when loading.  Do not
         * save it, as it would leak the QEMU address space layout.  */
        data.in_sg[i].iov_len = elem->in_sg[i].iov_len;
    }

    for (i = 0; i < elem->out_num; i++) {
        /* Do not save iov_base as above.  */
        data.out_sg[i].iov_len = elem->out_sg[i].iov_len;
    }
    qemu_put_buffer(f, (uint8_t *)&data, sizeof(VirtQueueElementOld));
686 687
}

A
aliguori 已提交
688
/* virtio device */
689 690
static void virtio_notify_vector(VirtIODevice *vdev, uint16_t vector)
{
K
KONRAD Frederic 已提交
691 692 693 694 695
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

    if (k->notify) {
        k->notify(qbus->parent, vector);
696 697
    }
}
A
aliguori 已提交
698

P
Paul Brook 已提交
699
void virtio_update_irq(VirtIODevice *vdev)
A
aliguori 已提交
700
{
701
    virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);
A
aliguori 已提交
702 703
}

704 705 706 707 708 709 710 711 712 713 714 715
static int virtio_validate_features(VirtIODevice *vdev)
{
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);

    if (k->validate_features) {
        return k->validate_features(vdev);
    } else {
        return 0;
    }
}

int virtio_set_status(VirtIODevice *vdev, uint8_t val)
716
{
717
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
718 719
    trace_virtio_set_status(vdev, val);

720
    if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
721 722 723 724 725 726 727 728 729
        if (!(vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) &&
            val & VIRTIO_CONFIG_S_FEATURES_OK) {
            int ret = virtio_validate_features(vdev);

            if (ret) {
                return ret;
            }
        }
    }
730 731
    if (k->set_status) {
        k->set_status(vdev, val);
732 733
    }
    vdev->status = val;
734
    return 0;
735 736
}

737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
bool target_words_bigendian(void);
static enum virtio_device_endian virtio_default_endian(void)
{
    if (target_words_bigendian()) {
        return VIRTIO_DEVICE_ENDIAN_BIG;
    } else {
        return VIRTIO_DEVICE_ENDIAN_LITTLE;
    }
}

static enum virtio_device_endian virtio_current_cpu_endian(void)
{
    CPUClass *cc = CPU_GET_CLASS(current_cpu);

    if (cc->virtio_is_big_endian(current_cpu)) {
        return VIRTIO_DEVICE_ENDIAN_BIG;
    } else {
        return VIRTIO_DEVICE_ENDIAN_LITTLE;
    }
}

P
Paul Brook 已提交
758
void virtio_reset(void *opaque)
A
aliguori 已提交
759 760
{
    VirtIODevice *vdev = opaque;
761
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
762 763
    int i;

764
    virtio_set_status(vdev, 0);
765 766 767 768 769 770 771
    if (current_cpu) {
        /* Guest initiated reset */
        vdev->device_endian = virtio_current_cpu_endian();
    } else {
        /* System reset */
        vdev->device_endian = virtio_default_endian();
    }
772

773 774 775
    if (k->reset) {
        k->reset(vdev);
    }
A
aliguori 已提交
776

777
    vdev->guest_features = 0;
A
aliguori 已提交
778 779 780
    vdev->queue_sel = 0;
    vdev->status = 0;
    vdev->isr = 0;
781 782
    vdev->config_vector = VIRTIO_NO_VECTOR;
    virtio_notify_vector(vdev, vdev->config_vector);
A
aliguori 已提交
783

784
    for(i = 0; i < VIRTIO_QUEUE_MAX; i++) {
A
aliguori 已提交
785 786 787 788
        vdev->vq[i].vring.desc = 0;
        vdev->vq[i].vring.avail = 0;
        vdev->vq[i].vring.used = 0;
        vdev->vq[i].last_avail_idx = 0;
789
        vdev->vq[i].used_idx = 0;
790
        virtio_queue_set_vector(vdev, i, VIRTIO_NO_VECTOR);
M
Michael S. Tsirkin 已提交
791 792 793
        vdev->vq[i].signalled_used = 0;
        vdev->vq[i].signalled_used_valid = false;
        vdev->vq[i].notification = true;
C
Cornelia Huck 已提交
794
        vdev->vq[i].vring.num = vdev->vq[i].vring.num_default;
A
aliguori 已提交
795 796 797
    }
}

P
Paul Brook 已提交
798
uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr)
A
aliguori 已提交
799
{
800
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
801 802
    uint8_t val;

803
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
804
        return (uint32_t)-1;
805 806 807
    }

    k->get_config(vdev, vdev->config);
A
aliguori 已提交
808

809
    val = ldub_p(vdev->config + addr);
A
aliguori 已提交
810 811 812
    return val;
}

P
Paul Brook 已提交
813
uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr)
A
aliguori 已提交
814
{
815
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
816 817
    uint16_t val;

818
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
819
        return (uint32_t)-1;
820 821 822
    }

    k->get_config(vdev, vdev->config);
A
aliguori 已提交
823

824
    val = lduw_p(vdev->config + addr);
A
aliguori 已提交
825 826 827
    return val;
}

P
Paul Brook 已提交
828
uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr)
A
aliguori 已提交
829
{
830
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
831 832
    uint32_t val;

833
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
834
        return (uint32_t)-1;
835 836 837
    }

    k->get_config(vdev, vdev->config);
A
aliguori 已提交
838

839
    val = ldl_p(vdev->config + addr);
A
aliguori 已提交
840 841 842
    return val;
}

P
Paul Brook 已提交
843
void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data)
A
aliguori 已提交
844
{
845
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
846 847
    uint8_t val = data;

848
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
849
        return;
850
    }
A
aliguori 已提交
851

852
    stb_p(vdev->config + addr, val);
A
aliguori 已提交
853

854 855 856
    if (k->set_config) {
        k->set_config(vdev, vdev->config);
    }
A
aliguori 已提交
857 858
}

P
Paul Brook 已提交
859
void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data)
A
aliguori 已提交
860
{
861
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
862 863
    uint16_t val = data;

864
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
865
        return;
866
    }
A
aliguori 已提交
867

868
    stw_p(vdev->config + addr, val);
A
aliguori 已提交
869

870 871 872
    if (k->set_config) {
        k->set_config(vdev, vdev->config);
    }
A
aliguori 已提交
873 874
}

P
Paul Brook 已提交
875
void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data)
A
aliguori 已提交
876
{
877
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
878 879
    uint32_t val = data;

880
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
881
        return;
882
    }
A
aliguori 已提交
883

884
    stl_p(vdev->config + addr, val);
A
aliguori 已提交
885

886 887 888
    if (k->set_config) {
        k->set_config(vdev, vdev->config);
    }
A
aliguori 已提交
889 890
}

891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr)
{
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
    uint8_t val;

    if (addr + sizeof(val) > vdev->config_len) {
        return (uint32_t)-1;
    }

    k->get_config(vdev, vdev->config);

    val = ldub_p(vdev->config + addr);
    return val;
}

uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr)
{
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
    uint16_t val;

    if (addr + sizeof(val) > vdev->config_len) {
        return (uint32_t)-1;
    }

    k->get_config(vdev, vdev->config);

    val = lduw_le_p(vdev->config + addr);
    return val;
}

uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr)
{
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
    uint32_t val;

    if (addr + sizeof(val) > vdev->config_len) {
        return (uint32_t)-1;
    }

    k->get_config(vdev, vdev->config);

    val = ldl_le_p(vdev->config + addr);
    return val;
}

void virtio_config_modern_writeb(VirtIODevice *vdev,
                                 uint32_t addr, uint32_t data)
{
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
    uint8_t val = data;

    if (addr + sizeof(val) > vdev->config_len) {
        return;
    }

    stb_p(vdev->config + addr, val);

    if (k->set_config) {
        k->set_config(vdev, vdev->config);
    }
}

void virtio_config_modern_writew(VirtIODevice *vdev,
                                 uint32_t addr, uint32_t data)
{
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
    uint16_t val = data;

    if (addr + sizeof(val) > vdev->config_len) {
        return;
    }

    stw_le_p(vdev->config + addr, val);

    if (k->set_config) {
        k->set_config(vdev, vdev->config);
    }
}

void virtio_config_modern_writel(VirtIODevice *vdev,
                                 uint32_t addr, uint32_t data)
{
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
    uint32_t val = data;

    if (addr + sizeof(val) > vdev->config_len) {
        return;
    }

    stl_le_p(vdev->config + addr, val);

    if (k->set_config) {
        k->set_config(vdev, vdev->config);
    }
}

A
Avi Kivity 已提交
987
void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr)
A
aliguori 已提交
988
{
989 990
    vdev->vq[n].vring.desc = addr;
    virtio_queue_update_rings(vdev, n);
P
Paul Brook 已提交
991 992
}

A
Avi Kivity 已提交
993
hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n)
P
Paul Brook 已提交
994
{
995 996 997 998 999 1000 1001 1002 1003
    return vdev->vq[n].vring.desc;
}

void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc,
                            hwaddr avail, hwaddr used)
{
    vdev->vq[n].vring.desc = desc;
    vdev->vq[n].vring.avail = avail;
    vdev->vq[n].vring.used = used;
P
Paul Brook 已提交
1004 1005
}

1006 1007
void virtio_queue_set_num(VirtIODevice *vdev, int n, int num)
{
1008 1009 1010 1011 1012 1013 1014
    /* Don't allow guest to flip queue between existent and
     * nonexistent states, or to set it to an invalid size.
     */
    if (!!num != !!vdev->vq[n].vring.num ||
        num > VIRTQUEUE_MAX_SIZE ||
        num < 0) {
        return;
1015
    }
1016
    vdev->vq[n].vring.num = num;
1017 1018
}

1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector)
{
    return QLIST_FIRST(&vdev->vector_queues[vector]);
}

VirtQueue *virtio_vector_next_queue(VirtQueue *vq)
{
    return QLIST_NEXT(vq, node);
}

P
Paul Brook 已提交
1029 1030 1031 1032
int virtio_queue_get_num(VirtIODevice *vdev, int n)
{
    return vdev->vq[n].vring.num;
}
A
aliguori 已提交
1033

1034 1035 1036 1037
int virtio_get_num_queues(VirtIODevice *vdev)
{
    int i;

1038
    for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
1039 1040 1041 1042 1043 1044 1045 1046
        if (!virtio_queue_get_num(vdev, i)) {
            break;
        }
    }

    return i;
}

P
Paolo Bonzini 已提交
1047 1048 1049
int virtio_queue_get_id(VirtQueue *vq)
{
    VirtIODevice *vdev = vq->vdev;
1050
    assert(vq >= &vdev->vq[0] && vq < &vdev->vq[VIRTIO_QUEUE_MAX]);
P
Paolo Bonzini 已提交
1051 1052 1053
    return vq - &vdev->vq[0];
}

1054 1055 1056 1057 1058
void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
{
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

1059
    /* virtio-1 compliant devices cannot change the alignment */
1060
    if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
1061 1062 1063
        error_report("tried to modify queue alignment for virtio-1 device");
        return;
    }
1064 1065 1066 1067 1068 1069 1070
    /* Check that the transport told us it was going to do this
     * (so a buggy transport will immediately assert rather than
     * silently failing to migrate this state)
     */
    assert(k->has_variable_vring_alignment);

    vdev->vq[n].vring.align = align;
1071
    virtio_queue_update_rings(vdev, n);
1072 1073
}

1074 1075
void virtio_queue_notify_vq(VirtQueue *vq)
{
1076
    if (vq->vring.desc && vq->handle_output) {
1077
        VirtIODevice *vdev = vq->vdev;
1078

1079 1080 1081 1082 1083
        trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
        vq->handle_output(vdev, vq);
    }
}

P
Paul Brook 已提交
1084 1085
void virtio_queue_notify(VirtIODevice *vdev, int n)
{
1086
    virtio_queue_notify_vq(&vdev->vq[n]);
A
aliguori 已提交
1087 1088
}

1089 1090
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
{
1091
    return n < VIRTIO_QUEUE_MAX ? vdev->vq[n].vector :
1092 1093 1094 1095 1096
        VIRTIO_NO_VECTOR;
}

void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector)
{
1097 1098
    VirtQueue *vq = &vdev->vq[n];

1099
    if (n < VIRTIO_QUEUE_MAX) {
1100 1101 1102 1103
        if (vdev->vector_queues &&
            vdev->vq[n].vector != VIRTIO_NO_VECTOR) {
            QLIST_REMOVE(vq, node);
        }
1104
        vdev->vq[n].vector = vector;
1105 1106 1107 1108 1109
        if (vdev->vector_queues &&
            vector != VIRTIO_NO_VECTOR) {
            QLIST_INSERT_HEAD(&vdev->vector_queues[vector], vq, node);
        }
    }
1110 1111
}

A
aliguori 已提交
1112 1113 1114 1115 1116
VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
                            void (*handle_output)(VirtIODevice *, VirtQueue *))
{
    int i;

1117
    for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
A
aliguori 已提交
1118 1119 1120 1121
        if (vdev->vq[i].vring.num == 0)
            break;
    }

1122
    if (i == VIRTIO_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)
A
aliguori 已提交
1123 1124 1125
        abort();

    vdev->vq[i].vring.num = queue_size;
C
Cornelia Huck 已提交
1126
    vdev->vq[i].vring.num_default = queue_size;
1127
    vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;
A
aliguori 已提交
1128 1129 1130 1131 1132
    vdev->vq[i].handle_output = handle_output;

    return &vdev->vq[i];
}

1133 1134
void virtio_del_queue(VirtIODevice *vdev, int n)
{
1135
    if (n < 0 || n >= VIRTIO_QUEUE_MAX) {
1136 1137 1138 1139
        abort();
    }

    vdev->vq[n].vring.num = 0;
C
Cornelia Huck 已提交
1140
    vdev->vq[n].vring.num_default = 0;
1141 1142
}

1143 1144
void virtio_irq(VirtQueue *vq)
{
1145
    trace_virtio_irq(vq);
1146 1147 1148 1149
    vq->vdev->isr |= 0x01;
    virtio_notify_vector(vq->vdev, vq->vector);
}

M
Michael S. Tsirkin 已提交
1150 1151 1152 1153
static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
{
    uint16_t old, new;
    bool v;
1154 1155
    /* We need to expose used array entries before checking used event. */
    smp_mb();
1156
    /* Always notify when queue is empty (when feature acknowledge) */
1157
    if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) &&
1158
        !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx) {
M
Michael S. Tsirkin 已提交
1159 1160 1161
        return true;
    }

1162
    if (!virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
M
Michael S. Tsirkin 已提交
1163 1164 1165 1166 1167 1168
        return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT);
    }

    v = vq->signalled_used_valid;
    vq->signalled_used_valid = true;
    old = vq->signalled_used;
1169
    new = vq->signalled_used = vq->used_idx;
1170
    return !v || vring_need_event(vring_get_used_event(vq), new, old);
M
Michael S. Tsirkin 已提交
1171 1172 1173 1174 1175
}

void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
{
    if (!vring_notify(vdev, vq)) {
A
aliguori 已提交
1176
        return;
M
Michael S. Tsirkin 已提交
1177
    }
A
aliguori 已提交
1178

1179
    trace_virtio_notify(vdev, vq);
A
aliguori 已提交
1180
    vdev->isr |= 0x01;
1181
    virtio_notify_vector(vdev, vq->vector);
A
aliguori 已提交
1182 1183 1184 1185
}

void virtio_notify_config(VirtIODevice *vdev)
{
1186 1187 1188
    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
        return;

A
aliguori 已提交
1189
    vdev->isr |= 0x03;
1190
    vdev->generation++;
1191
    virtio_notify_vector(vdev, vdev->config_vector);
A
aliguori 已提交
1192 1193
}

1194 1195 1196 1197 1198
static bool virtio_device_endian_needed(void *opaque)
{
    VirtIODevice *vdev = opaque;

    assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN);
1199
    if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
1200 1201 1202 1203
        return vdev->device_endian != virtio_default_endian();
    }
    /* Devices conforming to VIRTIO 1.0 or later are always LE. */
    return vdev->device_endian != VIRTIO_DEVICE_ENDIAN_LITTLE;
1204 1205
}

G
Gerd Hoffmann 已提交
1206 1207 1208 1209 1210 1211 1212
static bool virtio_64bit_features_needed(void *opaque)
{
    VirtIODevice *vdev = opaque;

    return (vdev->host_features >> 32) != 0;
}

J
Jason Wang 已提交
1213 1214 1215 1216 1217 1218 1219
static bool virtio_virtqueue_needed(void *opaque)
{
    VirtIODevice *vdev = opaque;

    return virtio_host_has_feature(vdev, VIRTIO_F_VERSION_1);
}

C
Cornelia Huck 已提交
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
static bool virtio_ringsize_needed(void *opaque)
{
    VirtIODevice *vdev = opaque;
    int i;

    for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
        if (vdev->vq[i].vring.num != vdev->vq[i].vring.num_default) {
            return true;
        }
    }
    return false;
}

1233 1234 1235 1236 1237 1238 1239 1240 1241 1242
static bool virtio_extra_state_needed(void *opaque)
{
    VirtIODevice *vdev = opaque;
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

    return k->has_extra_state &&
        k->has_extra_state(qbus->parent);
}

1243
static const VMStateDescription vmstate_virtqueue = {
J
Jason Wang 已提交
1244
    .name = "virtqueue_state",
1245 1246 1247 1248 1249 1250 1251
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT64(vring.avail, struct VirtQueue),
        VMSTATE_UINT64(vring.used, struct VirtQueue),
        VMSTATE_END_OF_LIST()
    }
J
Jason Wang 已提交
1252 1253 1254 1255 1256 1257 1258 1259
};

static const VMStateDescription vmstate_virtio_virtqueues = {
    .name = "virtio/virtqueues",
    .version_id = 1,
    .minimum_version_id = 1,
    .needed = &virtio_virtqueue_needed,
    .fields = (VMStateField[]) {
D
Dr. David Alan Gilbert 已提交
1260 1261
        VMSTATE_STRUCT_VARRAY_POINTER_KNOWN(vq, struct VirtIODevice,
                      VIRTIO_QUEUE_MAX, 0, vmstate_virtqueue, VirtQueue),
J
Jason Wang 已提交
1262 1263 1264 1265
        VMSTATE_END_OF_LIST()
    }
};

1266
static const VMStateDescription vmstate_ringsize = {
C
Cornelia Huck 已提交
1267
    .name = "ringsize_state",
1268 1269 1270 1271 1272 1273
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(vring.num_default, struct VirtQueue),
        VMSTATE_END_OF_LIST()
    }
C
Cornelia Huck 已提交
1274 1275 1276 1277 1278 1279 1280 1281
};

static const VMStateDescription vmstate_virtio_ringsize = {
    .name = "virtio/ringsize",
    .version_id = 1,
    .minimum_version_id = 1,
    .needed = &virtio_ringsize_needed,
    .fields = (VMStateField[]) {
D
Dr. David Alan Gilbert 已提交
1282 1283
        VMSTATE_STRUCT_VARRAY_POINTER_KNOWN(vq, struct VirtIODevice,
                      VIRTIO_QUEUE_MAX, 0, vmstate_ringsize, VirtQueue),
C
Cornelia Huck 已提交
1284 1285 1286 1287
        VMSTATE_END_OF_LIST()
    }
};

1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334
static int get_extra_state(QEMUFile *f, void *pv, size_t size)
{
    VirtIODevice *vdev = pv;
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

    if (!k->load_extra_state) {
        return -1;
    } else {
        return k->load_extra_state(qbus->parent, f);
    }
}

static void put_extra_state(QEMUFile *f, void *pv, size_t size)
{
    VirtIODevice *vdev = pv;
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

    k->save_extra_state(qbus->parent, f);
}

static const VMStateInfo vmstate_info_extra_state = {
    .name = "virtqueue_extra_state",
    .get = get_extra_state,
    .put = put_extra_state,
};

static const VMStateDescription vmstate_virtio_extra_state = {
    .name = "virtio/extra_state",
    .version_id = 1,
    .minimum_version_id = 1,
    .needed = &virtio_extra_state_needed,
    .fields = (VMStateField[]) {
        {
            .name         = "extra_state",
            .version_id   = 0,
            .field_exists = NULL,
            .size         = 0,
            .info         = &vmstate_info_extra_state,
            .flags        = VMS_SINGLE,
            .offset       = 0,
        },
        VMSTATE_END_OF_LIST()
    }
};

1335 1336 1337 1338
static const VMStateDescription vmstate_virtio_device_endian = {
    .name = "virtio/device_endian",
    .version_id = 1,
    .minimum_version_id = 1,
1339
    .needed = &virtio_device_endian_needed,
1340 1341 1342 1343 1344 1345
    .fields = (VMStateField[]) {
        VMSTATE_UINT8(device_endian, VirtIODevice),
        VMSTATE_END_OF_LIST()
    }
};

G
Gerd Hoffmann 已提交
1346 1347 1348 1349
static const VMStateDescription vmstate_virtio_64bit_features = {
    .name = "virtio/64bit_features",
    .version_id = 1,
    .minimum_version_id = 1,
1350
    .needed = &virtio_64bit_features_needed,
G
Gerd Hoffmann 已提交
1351 1352 1353 1354 1355 1356
    .fields = (VMStateField[]) {
        VMSTATE_UINT64(guest_features, VirtIODevice),
        VMSTATE_END_OF_LIST()
    }
};

1357 1358 1359 1360 1361 1362 1363
static const VMStateDescription vmstate_virtio = {
    .name = "virtio",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .fields = (VMStateField[]) {
        VMSTATE_END_OF_LIST()
1364
    },
1365 1366 1367
    .subsections = (const VMStateDescription*[]) {
        &vmstate_virtio_device_endian,
        &vmstate_virtio_64bit_features,
J
Jason Wang 已提交
1368
        &vmstate_virtio_virtqueues,
C
Cornelia Huck 已提交
1369
        &vmstate_virtio_ringsize,
1370
        &vmstate_virtio_extra_state,
1371
        NULL
1372 1373 1374
    }
};

A
aliguori 已提交
1375 1376
void virtio_save(VirtIODevice *vdev, QEMUFile *f)
{
K
KONRAD Frederic 已提交
1377 1378
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
1379
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
G
Gerd Hoffmann 已提交
1380
    uint32_t guest_features_lo = (vdev->guest_features & 0xffffffff);
A
aliguori 已提交
1381 1382
    int i;

K
KONRAD Frederic 已提交
1383 1384 1385
    if (k->save_config) {
        k->save_config(qbus->parent, f);
    }
A
aliguori 已提交
1386 1387 1388 1389

    qemu_put_8s(f, &vdev->status);
    qemu_put_8s(f, &vdev->isr);
    qemu_put_be16s(f, &vdev->queue_sel);
G
Gerd Hoffmann 已提交
1390
    qemu_put_be32s(f, &guest_features_lo);
A
aliguori 已提交
1391 1392 1393
    qemu_put_be32(f, vdev->config_len);
    qemu_put_buffer(f, vdev->config, vdev->config_len);

1394
    for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
A
aliguori 已提交
1395 1396 1397 1398 1399 1400
        if (vdev->vq[i].vring.num == 0)
            break;
    }

    qemu_put_be32(f, i);

1401
    for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
A
aliguori 已提交
1402 1403 1404 1405
        if (vdev->vq[i].vring.num == 0)
            break;

        qemu_put_be32(f, vdev->vq[i].vring.num);
1406 1407 1408
        if (k->has_variable_vring_alignment) {
            qemu_put_be32(f, vdev->vq[i].vring.align);
        }
1409 1410
        /* XXX virtio-1 devices */
        qemu_put_be64(f, vdev->vq[i].vring.desc);
A
aliguori 已提交
1411
        qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
K
KONRAD Frederic 已提交
1412 1413 1414
        if (k->save_queue) {
            k->save_queue(qbus->parent, i, f);
        }
A
aliguori 已提交
1415
    }
1416 1417 1418 1419

    if (vdc->save != NULL) {
        vdc->save(vdev, f);
    }
1420 1421

    /* Subsections */
1422
    vmstate_save_state(f, &vmstate_virtio, vdev, NULL);
A
aliguori 已提交
1423 1424
}

1425
static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val)
1426
{
1427
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
C
Cornelia Huck 已提交
1428
    bool bad = (val & ~(vdev->host_features)) != 0;
1429

C
Cornelia Huck 已提交
1430
    val &= vdev->host_features;
1431 1432
    if (k->set_features) {
        k->set_features(vdev, val);
1433 1434 1435 1436 1437
    }
    vdev->guest_features = val;
    return bad ? -1 : 0;
}

1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449
int virtio_set_features(VirtIODevice *vdev, uint64_t val)
{
   /*
     * The driver must not attempt to set features after feature negotiation
     * has finished.
     */
    if (vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) {
        return -EINVAL;
    }
    return virtio_set_features_nocheck(vdev, val);
}

1450
int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
A
aliguori 已提交
1451
{
1452
    int i, ret;
1453
    int32_t config_len;
1454
    uint32_t num;
1455
    uint32_t features;
K
KONRAD Frederic 已提交
1456 1457
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
1458
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
1459

1460 1461 1462 1463 1464 1465
    /*
     * We poison the endianness to ensure it does not get used before
     * subsections have been loaded.
     */
    vdev->device_endian = VIRTIO_DEVICE_ENDIAN_UNKNOWN;

K
KONRAD Frederic 已提交
1466 1467
    if (k->load_config) {
        ret = k->load_config(qbus->parent, f);
1468 1469 1470
        if (ret)
            return ret;
    }
A
aliguori 已提交
1471 1472 1473 1474

    qemu_get_8s(f, &vdev->status);
    qemu_get_8s(f, &vdev->isr);
    qemu_get_be16s(f, &vdev->queue_sel);
1475
    if (vdev->queue_sel >= VIRTIO_QUEUE_MAX) {
1476 1477
        return -1;
    }
1478
    qemu_get_be32s(f, &features);
1479

1480
    config_len = qemu_get_be32(f);
1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491

    /*
     * There are cases where the incoming config can be bigger or smaller
     * than what we have; so load what we have space for, and skip
     * any excess that's in the stream.
     */
    qemu_get_buffer(f, vdev->config, MIN(config_len, vdev->config_len));

    while (config_len > vdev->config_len) {
        qemu_get_byte(f);
        config_len--;
1492
    }
A
aliguori 已提交
1493 1494 1495

    num = qemu_get_be32(f);

1496
    if (num > VIRTIO_QUEUE_MAX) {
1497
        error_report("Invalid number of virtqueues: 0x%x", num);
1498 1499 1500
        return -1;
    }

A
aliguori 已提交
1501 1502
    for (i = 0; i < num; i++) {
        vdev->vq[i].vring.num = qemu_get_be32(f);
1503 1504 1505
        if (k->has_variable_vring_alignment) {
            vdev->vq[i].vring.align = qemu_get_be32(f);
        }
1506
        vdev->vq[i].vring.desc = qemu_get_be64(f);
A
aliguori 已提交
1507
        qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
M
Michael S. Tsirkin 已提交
1508 1509
        vdev->vq[i].signalled_used_valid = false;
        vdev->vq[i].notification = true;
A
aliguori 已提交
1510

1511 1512 1513
        if (vdev->vq[i].vring.desc) {
            /* XXX virtio-1 devices */
            virtio_queue_update_rings(vdev, i);
M
Michael S. Tsirkin 已提交
1514 1515
        } else if (vdev->vq[i].last_avail_idx) {
            error_report("VQ %d address 0x0 "
1516
                         "inconsistent with Host index 0x%x",
M
Michael S. Tsirkin 已提交
1517 1518
                         i, vdev->vq[i].last_avail_idx);
                return -1;
1519
	}
K
KONRAD Frederic 已提交
1520 1521
        if (k->load_queue) {
            ret = k->load_queue(qbus->parent, i, f);
1522 1523
            if (ret)
                return ret;
1524
        }
A
aliguori 已提交
1525 1526
    }

1527
    virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);
1528 1529

    if (vdc->load != NULL) {
1530 1531 1532 1533
        ret = vdc->load(vdev, f, version_id);
        if (ret) {
            return ret;
        }
1534 1535
    }

1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
    /* Subsections */
    ret = vmstate_load_state(f, &vmstate_virtio, vdev, 1);
    if (ret) {
        return ret;
    }

    if (vdev->device_endian == VIRTIO_DEVICE_ENDIAN_UNKNOWN) {
        vdev->device_endian = virtio_default_endian();
    }

G
Gerd Hoffmann 已提交
1546 1547 1548 1549 1550 1551 1552
    if (virtio_64bit_features_needed(vdev)) {
        /*
         * Subsection load filled vdev->guest_features.  Run them
         * through virtio_set_features to sanity-check them against
         * host_features.
         */
        uint64_t features64 = vdev->guest_features;
1553
        if (virtio_set_features_nocheck(vdev, features64) < 0) {
G
Gerd Hoffmann 已提交
1554 1555 1556 1557 1558 1559
            error_report("Features 0x%" PRIx64 " unsupported. "
                         "Allowed features: 0x%" PRIx64,
                         features64, vdev->host_features);
            return -1;
        }
    } else {
1560
        if (virtio_set_features_nocheck(vdev, features) < 0) {
G
Gerd Hoffmann 已提交
1561 1562 1563 1564 1565 1566 1567
            error_report("Features 0x%x unsupported. "
                         "Allowed features: 0x%" PRIx64,
                         features, vdev->host_features);
            return -1;
        }
    }

1568
    for (i = 0; i < num; i++) {
1569
        if (vdev->vq[i].vring.desc) {
1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580
            uint16_t nheads;
            nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;
            /* Check it isn't doing strange things with descriptor numbers. */
            if (nheads > vdev->vq[i].vring.num) {
                error_report("VQ %d size 0x%x Guest index 0x%x "
                             "inconsistent with Host index 0x%x: delta 0x%x",
                             i, vdev->vq[i].vring.num,
                             vring_avail_idx(&vdev->vq[i]),
                             vdev->vq[i].last_avail_idx, nheads);
                return -1;
            }
1581
            vdev->vq[i].used_idx = vring_used_idx(&vdev->vq[i]);
1582 1583 1584 1585
        }
    }

    return 0;
A
aliguori 已提交
1586 1587
}

1588
void virtio_cleanup(VirtIODevice *vdev)
1589
{
1590
    qemu_del_vm_change_state_handler(vdev->vmstate);
1591
    g_free(vdev->config);
1592
    g_free(vdev->vq);
1593
    g_free(vdev->vector_queues);
1594 1595
}

1596
static void virtio_vmstate_change(void *opaque, int running, RunState state)
1597 1598
{
    VirtIODevice *vdev = opaque;
K
KONRAD Frederic 已提交
1599 1600
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
1601
    bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
1602
    vdev->vm_running = running;
1603 1604 1605 1606 1607

    if (backend_run) {
        virtio_set_status(vdev, vdev->status);
    }

K
KONRAD Frederic 已提交
1608 1609
    if (k->vmstate_change) {
        k->vmstate_change(qbus->parent, backend_run);
1610 1611 1612 1613 1614 1615 1616
    }

    if (!backend_run) {
        virtio_set_status(vdev, vdev->status);
    }
}

1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627
void virtio_instance_init_common(Object *proxy_obj, void *data,
                                 size_t vdev_size, const char *vdev_name)
{
    DeviceState *vdev = data;

    object_initialize(vdev, vdev_size, vdev_name);
    object_property_add_child(proxy_obj, "virtio-backend", OBJECT(vdev), NULL);
    object_unref(OBJECT(vdev));
    qdev_alias_all_properties(vdev, proxy_obj);
}

1628 1629
void virtio_init(VirtIODevice *vdev, const char *name,
                 uint16_t device_id, size_t config_size)
A
aliguori 已提交
1630
{
1631 1632
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
1633
    int i;
1634 1635 1636 1637 1638 1639 1640
    int nvectors = k->query_nvectors ? k->query_nvectors(qbus->parent) : 0;

    if (nvectors) {
        vdev->vector_queues =
            g_malloc0(sizeof(*vdev->vector_queues) * nvectors);
    }

P
Paul Brook 已提交
1641
    vdev->device_id = device_id;
A
aliguori 已提交
1642 1643 1644
    vdev->status = 0;
    vdev->isr = 0;
    vdev->queue_sel = 0;
1645
    vdev->config_vector = VIRTIO_NO_VECTOR;
1646
    vdev->vq = g_malloc0(sizeof(VirtQueue) * VIRTIO_QUEUE_MAX);
1647
    vdev->vm_running = runstate_is_running();
1648
    for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
1649
        vdev->vq[i].vector = VIRTIO_NO_VECTOR;
1650
        vdev->vq[i].vdev = vdev;
1651
        vdev->vq[i].queue_index = i;
1652
    }
A
aliguori 已提交
1653 1654 1655

    vdev->name = name;
    vdev->config_len = config_size;
1656
    if (vdev->config_len) {
1657
        vdev->config = g_malloc0(config_size);
1658
    } else {
A
aliguori 已提交
1659
        vdev->config = NULL;
1660 1661 1662
    }
    vdev->vmstate = qemu_add_vm_change_state_handler(virtio_vmstate_change,
                                                     vdev);
1663
    vdev->device_endian = virtio_default_endian();
1664
}
A
aliguori 已提交
1665

A
Avi Kivity 已提交
1666
hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n)
1667 1668 1669 1670
{
    return vdev->vq[n].vring.desc;
}

A
Avi Kivity 已提交
1671
hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n)
1672 1673 1674 1675
{
    return vdev->vq[n].vring.avail;
}

A
Avi Kivity 已提交
1676
hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n)
1677 1678 1679 1680
{
    return vdev->vq[n].vring.used;
}

A
Avi Kivity 已提交
1681
hwaddr virtio_queue_get_ring_addr(VirtIODevice *vdev, int n)
1682 1683 1684 1685
{
    return vdev->vq[n].vring.desc;
}

A
Avi Kivity 已提交
1686
hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n)
1687 1688 1689 1690
{
    return sizeof(VRingDesc) * vdev->vq[n].vring.num;
}

A
Avi Kivity 已提交
1691
hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n)
1692 1693
{
    return offsetof(VRingAvail, ring) +
1694
        sizeof(uint16_t) * vdev->vq[n].vring.num;
1695 1696
}

A
Avi Kivity 已提交
1697
hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n)
1698 1699 1700 1701 1702
{
    return offsetof(VRingUsed, ring) +
        sizeof(VRingUsedElem) * vdev->vq[n].vring.num;
}

A
Avi Kivity 已提交
1703
hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n)
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718
{
    return vdev->vq[n].vring.used - vdev->vq[n].vring.desc +
	    virtio_queue_get_used_size(vdev, n);
}

uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n)
{
    return vdev->vq[n].last_avail_idx;
}

void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx)
{
    vdev->vq[n].last_avail_idx = idx;
}

1719 1720 1721 1722 1723
void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n)
{
    vdev->vq[n].signalled_used_valid = false;
}

1724 1725 1726 1727 1728
VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n)
{
    return vdev->vq + n;
}

1729 1730 1731 1732 1733
uint16_t virtio_get_queue_index(VirtQueue *vq)
{
    return vq->queue_index;
}

1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757
static void virtio_queue_guest_notifier_read(EventNotifier *n)
{
    VirtQueue *vq = container_of(n, VirtQueue, guest_notifier);
    if (event_notifier_test_and_clear(n)) {
        virtio_irq(vq);
    }
}

void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
                                                bool with_irqfd)
{
    if (assign && !with_irqfd) {
        event_notifier_set_handler(&vq->guest_notifier,
                                   virtio_queue_guest_notifier_read);
    } else {
        event_notifier_set_handler(&vq->guest_notifier, NULL);
    }
    if (!assign) {
        /* Test and clear notifier before closing it,
         * in case poll callback didn't have time to run. */
        virtio_queue_guest_notifier_read(&vq->guest_notifier);
    }
}

1758 1759 1760 1761
EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq)
{
    return &vq->guest_notifier;
}
1762 1763 1764 1765 1766 1767 1768 1769 1770

static void virtio_queue_host_notifier_read(EventNotifier *n)
{
    VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
    if (event_notifier_test_and_clear(n)) {
        virtio_queue_notify_vq(vq);
    }
}

P
Paolo Bonzini 已提交
1771 1772
void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign,
                                               bool set_handler)
1773
{
P
Paolo Bonzini 已提交
1774
    if (assign && set_handler) {
1775 1776 1777 1778
        event_notifier_set_handler(&vq->host_notifier,
                                   virtio_queue_host_notifier_read);
    } else {
        event_notifier_set_handler(&vq->host_notifier, NULL);
P
Paolo Bonzini 已提交
1779 1780
    }
    if (!assign) {
1781 1782 1783 1784 1785 1786
        /* Test and clear notifier before after disabling event,
         * in case poll callback didn't have time to run. */
        virtio_queue_host_notifier_read(&vq->host_notifier);
    }
}

1787 1788 1789 1790
EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq)
{
    return &vq->host_notifier;
}
1791

1792 1793
void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name)
{
1794
    g_free(vdev->bus_name);
1795
    vdev->bus_name = g_strdup(bus_name);
1796 1797
}

1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809
static void virtio_device_realize(DeviceState *dev, Error **errp)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
    Error *err = NULL;

    if (vdc->realize != NULL) {
        vdc->realize(dev, &err);
        if (err != NULL) {
            error_propagate(errp, err);
            return;
        }
1810
    }
J
Jason Wang 已提交
1811 1812 1813 1814 1815 1816

    virtio_bus_device_plugged(vdev, &err);
    if (err != NULL) {
        error_propagate(errp, err);
        return;
    }
1817 1818
}

1819
static void virtio_device_unrealize(DeviceState *dev, Error **errp)
1820
{
1821
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1822 1823
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
    Error *err = NULL;
1824

1825 1826
    virtio_bus_device_unplugged(vdev);

1827 1828 1829 1830 1831 1832
    if (vdc->unrealize != NULL) {
        vdc->unrealize(dev, &err);
        if (err != NULL) {
            error_propagate(errp, err);
            return;
        }
1833
    }
1834

1835 1836
    g_free(vdev->bus_name);
    vdev->bus_name = NULL;
1837 1838
}

C
Cornelia Huck 已提交
1839 1840 1841 1842 1843
static Property virtio_properties[] = {
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIODevice, host_features),
    DEFINE_PROP_END_OF_LIST(),
};

1844 1845 1846 1847
static void virtio_device_class_init(ObjectClass *klass, void *data)
{
    /* Set the default value here. */
    DeviceClass *dc = DEVICE_CLASS(klass);
1848 1849 1850

    dc->realize = virtio_device_realize;
    dc->unrealize = virtio_device_unrealize;
1851
    dc->bus_type = TYPE_VIRTIO_BUS;
C
Cornelia Huck 已提交
1852
    dc->props = virtio_properties;
1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869
}

static const TypeInfo virtio_device_info = {
    .name = TYPE_VIRTIO_DEVICE,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(VirtIODevice),
    .class_init = virtio_device_class_init,
    .abstract = true,
    .class_size = sizeof(VirtioDeviceClass),
};

static void virtio_register_types(void)
{
    type_register_static(&virtio_device_info);
}

type_init(virtio_register_types)