virtio.c 32.2 KB
Newer Older
A
aliguori 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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.
 *
 */

#include <inttypes.h>

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"
A
aliguori 已提交
22

23 24 25 26 27
/*
 * 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.
 */
28 29
#define VIRTIO_PCI_VRING_ALIGN         4096

A
aliguori 已提交
30 31 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
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;
61
    unsigned int align;
A
Avi Kivity 已提交
62 63 64
    hwaddr desc;
    hwaddr avail;
    hwaddr used;
A
aliguori 已提交
65 66 67 68 69
} VRing;

struct VirtQueue
{
    VRing vring;
A
Avi Kivity 已提交
70
    hwaddr pa;
A
aliguori 已提交
71
    uint16_t last_avail_idx;
M
Michael S. Tsirkin 已提交
72 73 74 75 76 77 78 79 80
    /* 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;

81 82
    uint16_t queue_index;

A
aliguori 已提交
83
    int inuse;
M
Michael S. Tsirkin 已提交
84

85
    uint16_t vector;
A
aliguori 已提交
86
    void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
87 88 89
    VirtIODevice *vdev;
    EventNotifier guest_notifier;
    EventNotifier host_notifier;
A
aliguori 已提交
90 91 92
};

/* virt queue functions */
P
Paul Brook 已提交
93
static void virtqueue_init(VirtQueue *vq)
A
aliguori 已提交
94
{
A
Avi Kivity 已提交
95
    hwaddr pa = vq->pa;
P
Paul Brook 已提交
96

A
aliguori 已提交
97 98
    vq->vring.desc = pa;
    vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc);
99 100
    vq->vring.used = vring_align(vq->vring.avail +
                                 offsetof(VRingAvail, ring[vq->vring.num]),
101
                                 vq->vring.align);
A
aliguori 已提交
102 103
}

A
Avi Kivity 已提交
104
static inline uint64_t vring_desc_addr(hwaddr desc_pa, int i)
A
aliguori 已提交
105
{
A
Avi Kivity 已提交
106
    hwaddr pa;
107
    pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr);
108
    return ldq_phys(&address_space_memory, pa);
A
aliguori 已提交
109 110
}

A
Avi Kivity 已提交
111
static inline uint32_t vring_desc_len(hwaddr desc_pa, int i)
A
aliguori 已提交
112
{
A
Avi Kivity 已提交
113
    hwaddr pa;
114
    pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, len);
115
    return ldl_phys(&address_space_memory, pa);
A
aliguori 已提交
116 117
}

A
Avi Kivity 已提交
118
static inline uint16_t vring_desc_flags(hwaddr desc_pa, int i)
A
aliguori 已提交
119
{
A
Avi Kivity 已提交
120
    hwaddr pa;
121
    pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags);
122
    return lduw_phys(&address_space_memory, pa);
A
aliguori 已提交
123 124
}

A
Avi Kivity 已提交
125
static inline uint16_t vring_desc_next(hwaddr desc_pa, int i)
A
aliguori 已提交
126
{
A
Avi Kivity 已提交
127
    hwaddr pa;
128
    pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, next);
129
    return lduw_phys(&address_space_memory, pa);
A
aliguori 已提交
130 131 132 133
}

static inline uint16_t vring_avail_flags(VirtQueue *vq)
{
A
Avi Kivity 已提交
134
    hwaddr pa;
A
aliguori 已提交
135
    pa = vq->vring.avail + offsetof(VRingAvail, flags);
136
    return lduw_phys(&address_space_memory, pa);
A
aliguori 已提交
137 138 139 140
}

static inline uint16_t vring_avail_idx(VirtQueue *vq)
{
A
Avi Kivity 已提交
141
    hwaddr pa;
A
aliguori 已提交
142
    pa = vq->vring.avail + offsetof(VRingAvail, idx);
143
    return lduw_phys(&address_space_memory, pa);
A
aliguori 已提交
144 145 146 147
}

static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)
{
A
Avi Kivity 已提交
148
    hwaddr pa;
A
aliguori 已提交
149
    pa = vq->vring.avail + offsetof(VRingAvail, ring[i]);
150
    return lduw_phys(&address_space_memory, pa);
A
aliguori 已提交
151 152
}

M
Michael S. Tsirkin 已提交
153 154 155 156 157
static inline uint16_t vring_used_event(VirtQueue *vq)
{
    return vring_avail_ring(vq, vq->vring.num);
}

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

static inline void vring_used_ring_len(VirtQueue *vq, int i, uint32_t val)
{
A
Avi Kivity 已提交
167
    hwaddr pa;
A
aliguori 已提交
168
    pa = vq->vring.used + offsetof(VRingUsed, ring[i].len);
169
    stl_phys(&address_space_memory, pa, val);
A
aliguori 已提交
170 171 172 173
}

static uint16_t vring_used_idx(VirtQueue *vq)
{
A
Avi Kivity 已提交
174
    hwaddr pa;
A
aliguori 已提交
175
    pa = vq->vring.used + offsetof(VRingUsed, idx);
176
    return lduw_phys(&address_space_memory, pa);
A
aliguori 已提交
177 178
}

M
Michael S. Tsirkin 已提交
179
static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val)
A
aliguori 已提交
180
{
A
Avi Kivity 已提交
181
    hwaddr pa;
A
aliguori 已提交
182
    pa = vq->vring.used + offsetof(VRingUsed, idx);
183
    stw_phys(&address_space_memory, pa, val);
A
aliguori 已提交
184 185 186 187
}

static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask)
{
A
Avi Kivity 已提交
188
    hwaddr pa;
A
aliguori 已提交
189
    pa = vq->vring.used + offsetof(VRingUsed, flags);
190 191
    stw_phys(&address_space_memory,
             pa, lduw_phys(&address_space_memory, pa) | mask);
A
aliguori 已提交
192 193 194 195
}

static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask)
{
A
Avi Kivity 已提交
196
    hwaddr pa;
A
aliguori 已提交
197
    pa = vq->vring.used + offsetof(VRingUsed, flags);
198 199
    stw_phys(&address_space_memory,
             pa, lduw_phys(&address_space_memory, pa) & ~mask);
A
aliguori 已提交
200 201
}

M
Michael S. Tsirkin 已提交
202 203
static inline void vring_avail_event(VirtQueue *vq, uint16_t val)
{
A
Avi Kivity 已提交
204
    hwaddr pa;
M
Michael S. Tsirkin 已提交
205 206 207 208
    if (!vq->notification) {
        return;
    }
    pa = vq->vring.used + offsetof(VRingUsed, ring[vq->vring.num]);
209
    stw_phys(&address_space_memory, pa, val);
M
Michael S. Tsirkin 已提交
210 211
}

A
aliguori 已提交
212 213
void virtio_queue_set_notification(VirtQueue *vq, int enable)
{
M
Michael S. Tsirkin 已提交
214 215 216 217
    vq->notification = enable;
    if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
        vring_avail_event(vq, vring_avail_idx(vq));
    } else if (enable) {
A
aliguori 已提交
218
        vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
M
Michael S. Tsirkin 已提交
219
    } else {
A
aliguori 已提交
220
        vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY);
M
Michael S. Tsirkin 已提交
221
    }
222 223 224 225
    if (enable) {
        /* Expose avail event/used flags before caller checks the avail idx. */
        smp_mb();
    }
A
aliguori 已提交
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
}

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;
}

void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
                    unsigned int len, unsigned int idx)
{
    unsigned int offset;
    int i;

244 245
    trace_virtqueue_fill(vq, elem, len, idx);

A
aliguori 已提交
246 247 248 249
    offset = 0;
    for (i = 0; i < elem->in_num; i++) {
        size_t size = MIN(len - offset, elem->in_sg[i].iov_len);

250 251 252
        cpu_physical_memory_unmap(elem->in_sg[i].iov_base,
                                  elem->in_sg[i].iov_len,
                                  1, size);
A
aliguori 已提交
253

254
        offset += size;
A
aliguori 已提交
255 256
    }

257 258 259 260 261
    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);

A
aliguori 已提交
262 263 264 265 266 267 268 269 270
    idx = (idx + vring_used_idx(vq)) % vq->vring.num;

    /* 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 已提交
271
    uint16_t old, new;
A
aliguori 已提交
272
    /* Make sure buffer is written before we update index. */
273
    smp_wmb();
274
    trace_virtqueue_flush(vq, count);
M
Michael S. Tsirkin 已提交
275 276 277
    old = vring_used_idx(vq);
    new = old + count;
    vring_used_idx_set(vq, new);
A
aliguori 已提交
278
    vq->inuse -= count;
M
Michael S. Tsirkin 已提交
279 280
    if (unlikely((int16_t)(new - vq->signalled_used) < (uint16_t)(new - old)))
        vq->signalled_used_valid = false;
A
aliguori 已提交
281 282 283 284 285 286 287 288 289 290 291 292 293 294
}

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 已提交
295
    if (num_heads > vq->vring.num) {
296 297
        error_report("Guest moved used index from %u to %u",
                     idx, vring_avail_idx(vq));
A
aliguori 已提交
298 299
        exit(1);
    }
300 301 302 303 304
    /* 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 已提交
305 306 307 308 309 310 311 312 313 314 315 316 317

    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 已提交
318
    if (head >= vq->vring.num) {
319
        error_report("Guest says index %u is available", head);
A
aliguori 已提交
320 321
        exit(1);
    }
A
aliguori 已提交
322 323 324 325

    return head;
}

A
Avi Kivity 已提交
326
static unsigned virtqueue_next_desc(hwaddr desc_pa,
327
                                    unsigned int i, unsigned int max)
A
aliguori 已提交
328 329 330 331
{
    unsigned int next;

    /* If this descriptor says it doesn't chain, we're done. */
332 333
    if (!(vring_desc_flags(desc_pa, i) & VRING_DESC_F_NEXT))
        return max;
A
aliguori 已提交
334 335

    /* Check they're not leading us off end of descriptors. */
336
    next = vring_desc_next(desc_pa, i);
A
aliguori 已提交
337
    /* Make sure compiler knows to grab that: we don't want it changing! */
338
    smp_wmb();
A
aliguori 已提交
339

340
    if (next >= max) {
341
        error_report("Desc next is %u", next);
A
aliguori 已提交
342 343
        exit(1);
    }
A
aliguori 已提交
344 345 346 347

    return next;
}

348
void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
349 350
                               unsigned int *out_bytes,
                               unsigned max_in_bytes, unsigned max_out_bytes)
A
aliguori 已提交
351
{
352
    unsigned int idx;
353
    unsigned int total_bufs, in_total, out_total;
A
aliguori 已提交
354 355 356

    idx = vq->last_avail_idx;

357
    total_bufs = in_total = out_total = 0;
A
aliguori 已提交
358
    while (virtqueue_num_heads(vq, idx)) {
359
        unsigned int max, num_bufs, indirect = 0;
A
Avi Kivity 已提交
360
        hwaddr desc_pa;
A
aliguori 已提交
361 362
        int i;

363 364
        max = vq->vring.num;
        num_bufs = total_bufs;
A
aliguori 已提交
365
        i = virtqueue_get_head(vq, idx++);
366 367 368 369
        desc_pa = vq->vring.desc;

        if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) {
            if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) {
370
                error_report("Invalid size for indirect buffer table");
371 372 373 374 375
                exit(1);
            }

            /* If we've got too many, that implies a descriptor loop. */
            if (num_bufs >= max) {
376
                error_report("Looped descriptor");
377 378 379 380 381 382 383
                exit(1);
            }

            /* loop over the indirect descriptor table */
            indirect = 1;
            max = vring_desc_len(desc_pa, i) / sizeof(VRingDesc);
            desc_pa = vring_desc_addr(desc_pa, i);
384
            num_bufs = i = 0;
385 386
        }

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

394
            if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
395
                in_total += vring_desc_len(desc_pa, i);
A
aliguori 已提交
396
            } else {
397
                out_total += vring_desc_len(desc_pa, i);
A
aliguori 已提交
398
            }
399 400 401
            if (in_total >= max_in_bytes && out_total >= max_out_bytes) {
                goto done;
            }
402
        } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
403 404 405 406 407

        if (!indirect)
            total_bufs = num_bufs;
        else
            total_bufs++;
A
aliguori 已提交
408
    }
409
done:
410 411 412 413 414 415 416
    if (in_bytes) {
        *in_bytes = in_total;
    }
    if (out_bytes) {
        *out_bytes = out_total;
    }
}
A
aliguori 已提交
417

418 419 420 421 422
int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
                          unsigned int out_bytes)
{
    unsigned int in_total, out_total;

423 424
    virtqueue_get_avail_bytes(vq, &in_total, &out_total, in_bytes, out_bytes);
    return in_bytes <= in_total && out_bytes <= out_total;
A
aliguori 已提交
425 426
}

A
Avi Kivity 已提交
427
void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
K
Kevin Wolf 已提交
428 429 430
    size_t num_sg, int is_write)
{
    unsigned int i;
A
Avi Kivity 已提交
431
    hwaddr len;
K
Kevin Wolf 已提交
432 433 434 435 436

    for (i = 0; i < num_sg; i++) {
        len = sg[i].iov_len;
        sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
        if (sg[i].iov_base == NULL || len != sg[i].iov_len) {
437
            error_report("virtio: trying to map MMIO memory");
K
Kevin Wolf 已提交
438 439 440 441 442
            exit(1);
        }
    }
}

A
aliguori 已提交
443 444
int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
{
445
    unsigned int i, head, max;
A
Avi Kivity 已提交
446
    hwaddr desc_pa = vq->vring.desc;
A
aliguori 已提交
447 448 449 450 451 452 453

    if (!virtqueue_num_heads(vq, vq->last_avail_idx))
        return 0;

    /* When we start there are none of either input nor output. */
    elem->out_num = elem->in_num = 0;

454 455
    max = vq->vring.num;

A
aliguori 已提交
456
    i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
M
Michael S. Tsirkin 已提交
457 458 459
    if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
        vring_avail_event(vq, vring_avail_idx(vq));
    }
460 461 462

    if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) {
        if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) {
463
            error_report("Invalid size for indirect buffer table");
464 465 466 467 468 469 470 471 472
            exit(1);
        }

        /* loop over the indirect descriptor table */
        max = vring_desc_len(desc_pa, i) / sizeof(VRingDesc);
        desc_pa = vring_desc_addr(desc_pa, i);
        i = 0;
    }

K
Kevin Wolf 已提交
473
    /* Collect all the descriptors */
A
aliguori 已提交
474 475 476
    do {
        struct iovec *sg;

477
        if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
478 479 480 481
            if (elem->in_num >= ARRAY_SIZE(elem->in_sg)) {
                error_report("Too many write descriptors in indirect table");
                exit(1);
            }
482
            elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
A
aliguori 已提交
483
            sg = &elem->in_sg[elem->in_num++];
K
Kevin Wolf 已提交
484
        } else {
485 486 487 488
            if (elem->out_num >= ARRAY_SIZE(elem->out_sg)) {
                error_report("Too many read descriptors in indirect table");
                exit(1);
            }
K
Kevin Wolf 已提交
489
            elem->out_addr[elem->out_num] = vring_desc_addr(desc_pa, i);
A
aliguori 已提交
490
            sg = &elem->out_sg[elem->out_num++];
K
Kevin Wolf 已提交
491
        }
A
aliguori 已提交
492

493
        sg->iov_len = vring_desc_len(desc_pa, i);
A
aliguori 已提交
494 495

        /* If we've got too many, that implies a descriptor loop. */
496
        if ((elem->in_num + elem->out_num) > max) {
497
            error_report("Looped descriptor");
A
aliguori 已提交
498 499
            exit(1);
        }
500
    } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
A
aliguori 已提交
501

K
Kevin Wolf 已提交
502 503 504 505
    /* Now map what we have collected */
    virtqueue_map_sg(elem->in_sg, elem->in_addr, elem->in_num, 1);
    virtqueue_map_sg(elem->out_sg, elem->out_addr, elem->out_num, 0);

A
aliguori 已提交
506 507 508 509
    elem->index = head;

    vq->inuse++;

510
    trace_virtqueue_pop(vq, elem, elem->in_num, elem->out_num);
A
aliguori 已提交
511 512 513 514
    return elem->in_num + elem->out_num;
}

/* virtio device */
515 516
static void virtio_notify_vector(VirtIODevice *vdev, uint16_t vector)
{
K
KONRAD Frederic 已提交
517 518 519 520 521
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

    if (k->notify) {
        k->notify(qbus->parent, vector);
522 523
    }
}
A
aliguori 已提交
524

P
Paul Brook 已提交
525
void virtio_update_irq(VirtIODevice *vdev)
A
aliguori 已提交
526
{
527
    virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);
A
aliguori 已提交
528 529
}

530 531
void virtio_set_status(VirtIODevice *vdev, uint8_t val)
{
532
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
533 534
    trace_virtio_set_status(vdev, val);

535 536
    if (k->set_status) {
        k->set_status(vdev, val);
537 538 539 540
    }
    vdev->status = val;
}

P
Paul Brook 已提交
541
void virtio_reset(void *opaque)
A
aliguori 已提交
542 543
{
    VirtIODevice *vdev = opaque;
544
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
545 546
    int i;

547 548
    virtio_set_status(vdev, 0);

549 550 551
    if (k->reset) {
        k->reset(vdev);
    }
A
aliguori 已提交
552

553
    vdev->guest_features = 0;
A
aliguori 已提交
554 555 556
    vdev->queue_sel = 0;
    vdev->status = 0;
    vdev->isr = 0;
557 558
    vdev->config_vector = VIRTIO_NO_VECTOR;
    virtio_notify_vector(vdev, vdev->config_vector);
A
aliguori 已提交
559 560 561 562 563 564

    for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
        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;
P
Paul Brook 已提交
565
        vdev->vq[i].pa = 0;
566
        vdev->vq[i].vector = VIRTIO_NO_VECTOR;
M
Michael S. Tsirkin 已提交
567 568 569
        vdev->vq[i].signalled_used = 0;
        vdev->vq[i].signalled_used_valid = false;
        vdev->vq[i].notification = true;
A
aliguori 已提交
570 571 572
    }
}

P
Paul Brook 已提交
573
uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr)
A
aliguori 已提交
574
{
575
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
576 577
    uint8_t val;

578
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
579
        return (uint32_t)-1;
580 581 582
    }

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

584
    val = ldub_p(vdev->config + addr);
A
aliguori 已提交
585 586 587
    return val;
}

P
Paul Brook 已提交
588
uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr)
A
aliguori 已提交
589
{
590
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
591 592
    uint16_t val;

593
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
594
        return (uint32_t)-1;
595 596 597
    }

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

599
    val = lduw_p(vdev->config + addr);
A
aliguori 已提交
600 601 602
    return val;
}

P
Paul Brook 已提交
603
uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr)
A
aliguori 已提交
604
{
605
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
606 607
    uint32_t val;

608
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
609
        return (uint32_t)-1;
610 611 612
    }

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

614
    val = ldl_p(vdev->config + addr);
A
aliguori 已提交
615 616 617
    return val;
}

P
Paul Brook 已提交
618
void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data)
A
aliguori 已提交
619
{
620
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
621 622
    uint8_t val = data;

623
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
624
        return;
625
    }
A
aliguori 已提交
626

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

629 630 631
    if (k->set_config) {
        k->set_config(vdev, vdev->config);
    }
A
aliguori 已提交
632 633
}

P
Paul Brook 已提交
634
void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data)
A
aliguori 已提交
635
{
636
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
637 638
    uint16_t val = data;

639
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
640
        return;
641
    }
A
aliguori 已提交
642

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

645 646 647
    if (k->set_config) {
        k->set_config(vdev, vdev->config);
    }
A
aliguori 已提交
648 649
}

P
Paul Brook 已提交
650
void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data)
A
aliguori 已提交
651
{
652
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
A
aliguori 已提交
653 654
    uint32_t val = data;

655
    if (addr + sizeof(val) > vdev->config_len) {
A
aliguori 已提交
656
        return;
657
    }
A
aliguori 已提交
658

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

661 662 663
    if (k->set_config) {
        k->set_config(vdev, vdev->config);
    }
A
aliguori 已提交
664 665
}

A
Avi Kivity 已提交
666
void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr)
A
aliguori 已提交
667
{
668 669
    vdev->vq[n].pa = addr;
    virtqueue_init(&vdev->vq[n]);
P
Paul Brook 已提交
670 671
}

A
Avi Kivity 已提交
672
hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n)
P
Paul Brook 已提交
673 674 675 676
{
    return vdev->vq[n].pa;
}

677 678
void virtio_queue_set_num(VirtIODevice *vdev, int n, int num)
{
679 680 681 682 683 684 685
    /* 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;
686
    }
687 688
    vdev->vq[n].vring.num = num;
    virtqueue_init(&vdev->vq[n]);
689 690
}

P
Paul Brook 已提交
691 692 693 694
int virtio_queue_get_num(VirtIODevice *vdev, int n)
{
    return vdev->vq[n].vring.num;
}
A
aliguori 已提交
695

P
Paolo Bonzini 已提交
696 697 698 699 700 701 702
int virtio_queue_get_id(VirtQueue *vq)
{
    VirtIODevice *vdev = vq->vdev;
    assert(vq >= &vdev->vq[0] && vq < &vdev->vq[VIRTIO_PCI_QUEUE_MAX]);
    return vq - &vdev->vq[0];
}

703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
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);

    /* 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;
    virtqueue_init(&vdev->vq[n]);
}

718 719 720 721 722 723 724 725 726
void virtio_queue_notify_vq(VirtQueue *vq)
{
    if (vq->vring.desc) {
        VirtIODevice *vdev = vq->vdev;
        trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
        vq->handle_output(vdev, vq);
    }
}

P
Paul Brook 已提交
727 728
void virtio_queue_notify(VirtIODevice *vdev, int n)
{
729
    virtio_queue_notify_vq(&vdev->vq[n]);
A
aliguori 已提交
730 731
}

732 733 734 735 736 737 738 739 740 741 742 743
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
{
    return n < VIRTIO_PCI_QUEUE_MAX ? vdev->vq[n].vector :
        VIRTIO_NO_VECTOR;
}

void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector)
{
    if (n < VIRTIO_PCI_QUEUE_MAX)
        vdev->vq[n].vector = vector;
}

A
aliguori 已提交
744 745 746 747 748 749 750 751 752 753 754 755 756 757
VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
                            void (*handle_output)(VirtIODevice *, VirtQueue *))
{
    int i;

    for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
        if (vdev->vq[i].vring.num == 0)
            break;
    }

    if (i == VIRTIO_PCI_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)
        abort();

    vdev->vq[i].vring.num = queue_size;
758
    vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;
A
aliguori 已提交
759 760 761 762 763
    vdev->vq[i].handle_output = handle_output;

    return &vdev->vq[i];
}

764 765 766 767 768 769 770 771 772
void virtio_del_queue(VirtIODevice *vdev, int n)
{
    if (n < 0 || n >= VIRTIO_PCI_QUEUE_MAX) {
        abort();
    }

    vdev->vq[n].vring.num = 0;
}

773 774
void virtio_irq(VirtQueue *vq)
{
775
    trace_virtio_irq(vq);
776 777 778 779
    vq->vdev->isr |= 0x01;
    virtio_notify_vector(vq->vdev, vq->vector);
}

M
Michael S. Tsirkin 已提交
780 781 782 783
/* Assuming a given event_idx value from the other size, if
 * we have just incremented index from old to new_idx,
 * should we trigger an event? */
static inline int vring_need_event(uint16_t event, uint16_t new, uint16_t old)
A
aliguori 已提交
784
{
M
Michael S. Tsirkin 已提交
785 786 787 788 789 790 791 792 793 794 795 796
	/* Note: Xen has similar logic for notification hold-off
	 * in include/xen/interface/io/ring.h with req_event and req_prod
	 * corresponding to event_idx + 1 and new respectively.
	 * Note also that req_event and req_prod in Xen start at 1,
	 * event indexes in virtio start at 0. */
	return (uint16_t)(new - event - 1) < (uint16_t)(new - old);
}

static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
{
    uint16_t old, new;
    bool v;
797 798
    /* We need to expose used array entries before checking used event. */
    smp_mb();
799
    /* Always notify when queue is empty (when feature acknowledge) */
M
Michael S. Tsirkin 已提交
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
    if (((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) &&
         !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx)) {
        return true;
    }

    if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
        return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT);
    }

    v = vq->signalled_used_valid;
    vq->signalled_used_valid = true;
    old = vq->signalled_used;
    new = vq->signalled_used = vring_used_idx(vq);
    return !v || vring_need_event(vring_used_event(vq), new, old);
}

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

822
    trace_virtio_notify(vdev, vq);
A
aliguori 已提交
823
    vdev->isr |= 0x01;
824
    virtio_notify_vector(vdev, vq->vector);
A
aliguori 已提交
825 826 827 828
}

void virtio_notify_config(VirtIODevice *vdev)
{
829 830 831
    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
        return;

A
aliguori 已提交
832
    vdev->isr |= 0x03;
833
    virtio_notify_vector(vdev, vdev->config_vector);
A
aliguori 已提交
834 835 836 837
}

void virtio_save(VirtIODevice *vdev, QEMUFile *f)
{
K
KONRAD Frederic 已提交
838 839
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
A
aliguori 已提交
840 841
    int i;

K
KONRAD Frederic 已提交
842 843 844
    if (k->save_config) {
        k->save_config(qbus->parent, f);
    }
A
aliguori 已提交
845 846 847 848

    qemu_put_8s(f, &vdev->status);
    qemu_put_8s(f, &vdev->isr);
    qemu_put_be16s(f, &vdev->queue_sel);
849
    qemu_put_be32s(f, &vdev->guest_features);
A
aliguori 已提交
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
    qemu_put_be32(f, vdev->config_len);
    qemu_put_buffer(f, vdev->config, vdev->config_len);

    for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
        if (vdev->vq[i].vring.num == 0)
            break;
    }

    qemu_put_be32(f, i);

    for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
        if (vdev->vq[i].vring.num == 0)
            break;

        qemu_put_be32(f, vdev->vq[i].vring.num);
865 866 867
        if (k->has_variable_vring_alignment) {
            qemu_put_be32(f, vdev->vq[i].vring.align);
        }
P
Paul Brook 已提交
868
        qemu_put_be64(f, vdev->vq[i].pa);
A
aliguori 已提交
869
        qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
K
KONRAD Frederic 已提交
870 871 872
        if (k->save_queue) {
            k->save_queue(qbus->parent, i, f);
        }
A
aliguori 已提交
873 874 875
    }
}

876 877
int virtio_set_features(VirtIODevice *vdev, uint32_t val)
{
K
KONRAD Frederic 已提交
878 879
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *vbusk = VIRTIO_BUS_GET_CLASS(qbus);
880
    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
K
KONRAD Frederic 已提交
881
    uint32_t supported_features = vbusk->get_features(qbus->parent);
882 883 884
    bool bad = (val & ~supported_features) != 0;

    val &= supported_features;
885 886
    if (k->set_features) {
        k->set_features(vdev, val);
887 888 889 890 891
    }
    vdev->guest_features = val;
    return bad ? -1 : 0;
}

892
int virtio_load(VirtIODevice *vdev, QEMUFile *f)
A
aliguori 已提交
893
{
894
    int num, i, ret;
895
    uint32_t features;
896
    uint32_t supported_features;
K
KONRAD Frederic 已提交
897 898
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
A
aliguori 已提交
899

K
KONRAD Frederic 已提交
900 901
    if (k->load_config) {
        ret = k->load_config(qbus->parent, f);
902 903 904
        if (ret)
            return ret;
    }
A
aliguori 已提交
905 906 907 908

    qemu_get_8s(f, &vdev->status);
    qemu_get_8s(f, &vdev->isr);
    qemu_get_be16s(f, &vdev->queue_sel);
909
    qemu_get_be32s(f, &features);
910 911

    if (virtio_set_features(vdev, features) < 0) {
K
KONRAD Frederic 已提交
912
        supported_features = k->get_features(qbus->parent);
913 914
        error_report("Features 0x%x unsupported. Allowed features: 0x%x",
                     features, supported_features);
915 916
        return -1;
    }
A
aliguori 已提交
917 918 919 920 921 922 923
    vdev->config_len = qemu_get_be32(f);
    qemu_get_buffer(f, vdev->config, vdev->config_len);

    num = qemu_get_be32(f);

    for (i = 0; i < num; i++) {
        vdev->vq[i].vring.num = qemu_get_be32(f);
924 925 926
        if (k->has_variable_vring_alignment) {
            vdev->vq[i].vring.align = qemu_get_be32(f);
        }
P
Paul Brook 已提交
927
        vdev->vq[i].pa = qemu_get_be64(f);
A
aliguori 已提交
928
        qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
M
Michael S. Tsirkin 已提交
929 930
        vdev->vq[i].signalled_used_valid = false;
        vdev->vq[i].notification = true;
A
aliguori 已提交
931

P
Paul Brook 已提交
932
        if (vdev->vq[i].pa) {
M
Michael S. Tsirkin 已提交
933
            uint16_t nheads;
P
Paul Brook 已提交
934
            virtqueue_init(&vdev->vq[i]);
M
Michael S. Tsirkin 已提交
935 936 937 938
            nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;
            /* Check it isn't doing very strange things with descriptor numbers. */
            if (nheads > vdev->vq[i].vring.num) {
                error_report("VQ %d size 0x%x Guest index 0x%x "
939
                             "inconsistent with Host index 0x%x: delta 0x%x",
M
Michael S. Tsirkin 已提交
940 941 942 943 944 945 946
                             i, vdev->vq[i].vring.num,
                             vring_avail_idx(&vdev->vq[i]),
                             vdev->vq[i].last_avail_idx, nheads);
                return -1;
            }
        } else if (vdev->vq[i].last_avail_idx) {
            error_report("VQ %d address 0x0 "
947
                         "inconsistent with Host index 0x%x",
M
Michael S. Tsirkin 已提交
948 949
                         i, vdev->vq[i].last_avail_idx);
                return -1;
950
	}
K
KONRAD Frederic 已提交
951 952
        if (k->load_queue) {
            ret = k->load_queue(qbus->parent, i, f);
953 954
            if (ret)
                return ret;
955
        }
A
aliguori 已提交
956 957
    }

958
    virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);
959
    return 0;
A
aliguori 已提交
960 961
}

962
void virtio_cleanup(VirtIODevice *vdev)
963
{
964
    qemu_del_vm_change_state_handler(vdev->vmstate);
965
    g_free(vdev->config);
966
    g_free(vdev->vq);
967 968
}

969
static void virtio_vmstate_change(void *opaque, int running, RunState state)
970 971
{
    VirtIODevice *vdev = opaque;
K
KONRAD Frederic 已提交
972 973
    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
974 975 976 977 978 979 980
    bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
    vdev->vm_running = running;

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

K
KONRAD Frederic 已提交
981 982
    if (k->vmstate_change) {
        k->vmstate_change(qbus->parent, backend_run);
983 984 985 986 987 988 989
    }

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

990 991
void virtio_init(VirtIODevice *vdev, const char *name,
                 uint16_t device_id, size_t config_size)
A
aliguori 已提交
992
{
993
    int i;
P
Paul Brook 已提交
994
    vdev->device_id = device_id;
A
aliguori 已提交
995 996 997
    vdev->status = 0;
    vdev->isr = 0;
    vdev->queue_sel = 0;
998
    vdev->config_vector = VIRTIO_NO_VECTOR;
999
    vdev->vq = g_malloc0(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
1000
    vdev->vm_running = runstate_is_running();
1001
    for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
1002
        vdev->vq[i].vector = VIRTIO_NO_VECTOR;
1003
        vdev->vq[i].vdev = vdev;
1004
        vdev->vq[i].queue_index = i;
1005
    }
A
aliguori 已提交
1006 1007 1008

    vdev->name = name;
    vdev->config_len = config_size;
1009
    if (vdev->config_len) {
1010
        vdev->config = g_malloc0(config_size);
1011
    } else {
A
aliguori 已提交
1012
        vdev->config = NULL;
1013 1014 1015 1016
    }
    vdev->vmstate = qemu_add_vm_change_state_handler(virtio_vmstate_change,
                                                     vdev);
}
A
aliguori 已提交
1017

A
Avi Kivity 已提交
1018
hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n)
1019 1020 1021 1022
{
    return vdev->vq[n].vring.desc;
}

A
Avi Kivity 已提交
1023
hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n)
1024 1025 1026 1027
{
    return vdev->vq[n].vring.avail;
}

A
Avi Kivity 已提交
1028
hwaddr virtio_queue_get_used_addr(VirtIODevice *vdev, int n)
1029 1030 1031 1032
{
    return vdev->vq[n].vring.used;
}

A
Avi Kivity 已提交
1033
hwaddr virtio_queue_get_ring_addr(VirtIODevice *vdev, int n)
1034 1035 1036 1037
{
    return vdev->vq[n].vring.desc;
}

A
Avi Kivity 已提交
1038
hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n)
1039 1040 1041 1042
{
    return sizeof(VRingDesc) * vdev->vq[n].vring.num;
}

A
Avi Kivity 已提交
1043
hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n)
1044 1045
{
    return offsetof(VRingAvail, ring) +
1046
        sizeof(uint64_t) * vdev->vq[n].vring.num;
1047 1048
}

A
Avi Kivity 已提交
1049
hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n)
1050 1051 1052 1053 1054
{
    return offsetof(VRingUsed, ring) +
        sizeof(VRingUsedElem) * vdev->vq[n].vring.num;
}

A
Avi Kivity 已提交
1055
hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n)
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
{
    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;
}

1071 1072 1073 1074 1075
void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n)
{
    vdev->vq[n].signalled_used_valid = false;
}

1076 1077 1078 1079 1080
VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n)
{
    return vdev->vq + n;
}

1081 1082 1083 1084 1085
uint16_t virtio_get_queue_index(VirtQueue *vq)
{
    return vq->queue_index;
}

1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
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);
    }
}

1110 1111 1112 1113
EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq)
{
    return &vq->guest_notifier;
}
1114 1115 1116 1117 1118 1119 1120 1121 1122

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 已提交
1123 1124
void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign,
                                               bool set_handler)
1125
{
P
Paolo Bonzini 已提交
1126
    if (assign && set_handler) {
1127 1128 1129 1130
        event_notifier_set_handler(&vq->host_notifier,
                                   virtio_queue_host_notifier_read);
    } else {
        event_notifier_set_handler(&vq->host_notifier, NULL);
P
Paolo Bonzini 已提交
1131 1132
    }
    if (!assign) {
1133 1134 1135 1136 1137 1138
        /* 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);
    }
}

1139 1140 1141 1142
EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq)
{
    return &vq->host_notifier;
}
1143

1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name)
{
    if (vdev->bus_name) {
        g_free(vdev->bus_name);
        vdev->bus_name = NULL;
    }

    if (bus_name) {
        vdev->bus_name = g_strdup(bus_name);
    }
}

1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167
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;
        }
1168
    }
1169
    virtio_bus_device_plugged(vdev);
1170 1171
}

1172
static void virtio_device_unrealize(DeviceState *dev, Error **errp)
1173
{
1174
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1175 1176
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
    Error *err = NULL;
1177

1178 1179
    virtio_bus_device_unplugged(vdev);

1180 1181 1182 1183 1184 1185
    if (vdc->unrealize != NULL) {
        vdc->unrealize(dev, &err);
        if (err != NULL) {
            error_propagate(errp, err);
            return;
        }
1186
    }
1187

1188 1189 1190 1191 1192 1193
    if (vdev->bus_name) {
        g_free(vdev->bus_name);
        vdev->bus_name = NULL;
    }
}

1194 1195 1196 1197
static void virtio_device_class_init(ObjectClass *klass, void *data)
{
    /* Set the default value here. */
    DeviceClass *dc = DEVICE_CLASS(klass);
1198 1199 1200

    dc->realize = virtio_device_realize;
    dc->unrealize = virtio_device_unrealize;
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
    dc->bus_type = TYPE_VIRTIO_BUS;
}

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)