Annotation of qemu/hw/virtio.c, revision 1.1.1.8

1.1       root        1: /*
                      2:  * Virtio Support
                      3:  *
                      4:  * Copyright IBM, Corp. 2007
                      5:  *
                      6:  * Authors:
                      7:  *  Anthony Liguori   <[email protected]>
                      8:  *
                      9:  * This work is licensed under the terms of the GNU GPL, version 2.  See
                     10:  * the COPYING file in the top-level directory.
                     11:  *
                     12:  */
                     13: 
                     14: #include <inttypes.h>
                     15: 
1.1.1.8 ! root       16: #include "trace.h"
        !            17: #include "qemu-error.h"
1.1       root       18: #include "virtio.h"
                     19: #include "sysemu.h"
                     20: 
                     21: /* The alignment to use between consumer and producer parts of vring.
                     22:  * x86 pagesize again. */
                     23: #define VIRTIO_PCI_VRING_ALIGN         4096
                     24: 
                     25: /* QEMU doesn't strictly need write barriers since everything runs in
                     26:  * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
                     27:  * KVM or if kqemu gets SMP support.
1.1.1.6   root       28:  * In any case, we must prevent the compiler from reordering the code.
                     29:  * TODO: we likely need some rmb()/mb() as well.
1.1       root       30:  */
1.1.1.6   root       31: 
                     32: #define wmb() __asm__ __volatile__("": : :"memory")
1.1       root       33: 
                     34: typedef struct VRingDesc
                     35: {
                     36:     uint64_t addr;
                     37:     uint32_t len;
                     38:     uint16_t flags;
                     39:     uint16_t next;
                     40: } VRingDesc;
                     41: 
                     42: typedef struct VRingAvail
                     43: {
                     44:     uint16_t flags;
                     45:     uint16_t idx;
                     46:     uint16_t ring[0];
                     47: } VRingAvail;
                     48: 
                     49: typedef struct VRingUsedElem
                     50: {
                     51:     uint32_t id;
                     52:     uint32_t len;
                     53: } VRingUsedElem;
                     54: 
                     55: typedef struct VRingUsed
                     56: {
                     57:     uint16_t flags;
                     58:     uint16_t idx;
                     59:     VRingUsedElem ring[0];
                     60: } VRingUsed;
                     61: 
                     62: typedef struct VRing
                     63: {
                     64:     unsigned int num;
                     65:     target_phys_addr_t desc;
                     66:     target_phys_addr_t avail;
                     67:     target_phys_addr_t used;
                     68: } VRing;
                     69: 
                     70: struct VirtQueue
                     71: {
                     72:     VRing vring;
1.1.1.5   root       73:     target_phys_addr_t pa;
1.1       root       74:     uint16_t last_avail_idx;
                     75:     int inuse;
1.1.1.5   root       76:     uint16_t vector;
1.1       root       77:     void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
1.1.1.7   root       78:     VirtIODevice *vdev;
                     79:     EventNotifier guest_notifier;
                     80:     EventNotifier host_notifier;
1.1       root       81: };
                     82: 
                     83: /* virt queue functions */
1.1.1.5   root       84: static void virtqueue_init(VirtQueue *vq)
1.1       root       85: {
1.1.1.5   root       86:     target_phys_addr_t pa = vq->pa;
1.1       root       87: 
                     88:     vq->vring.desc = pa;
                     89:     vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc);
                     90:     vq->vring.used = vring_align(vq->vring.avail +
                     91:                                  offsetof(VRingAvail, ring[vq->vring.num]),
                     92:                                  VIRTIO_PCI_VRING_ALIGN);
                     93: }
                     94: 
1.1.1.5   root       95: static inline uint64_t vring_desc_addr(target_phys_addr_t desc_pa, int i)
1.1       root       96: {
                     97:     target_phys_addr_t pa;
1.1.1.5   root       98:     pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr);
1.1       root       99:     return ldq_phys(pa);
                    100: }
                    101: 
1.1.1.5   root      102: static inline uint32_t vring_desc_len(target_phys_addr_t desc_pa, int i)
1.1       root      103: {
                    104:     target_phys_addr_t pa;
1.1.1.5   root      105:     pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, len);
1.1       root      106:     return ldl_phys(pa);
                    107: }
                    108: 
1.1.1.5   root      109: static inline uint16_t vring_desc_flags(target_phys_addr_t desc_pa, int i)
1.1       root      110: {
                    111:     target_phys_addr_t pa;
1.1.1.5   root      112:     pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags);
1.1       root      113:     return lduw_phys(pa);
                    114: }
                    115: 
1.1.1.5   root      116: static inline uint16_t vring_desc_next(target_phys_addr_t desc_pa, int i)
1.1       root      117: {
                    118:     target_phys_addr_t pa;
1.1.1.5   root      119:     pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, next);
1.1       root      120:     return lduw_phys(pa);
                    121: }
                    122: 
                    123: static inline uint16_t vring_avail_flags(VirtQueue *vq)
                    124: {
                    125:     target_phys_addr_t pa;
                    126:     pa = vq->vring.avail + offsetof(VRingAvail, flags);
                    127:     return lduw_phys(pa);
                    128: }
                    129: 
                    130: static inline uint16_t vring_avail_idx(VirtQueue *vq)
                    131: {
                    132:     target_phys_addr_t pa;
                    133:     pa = vq->vring.avail + offsetof(VRingAvail, idx);
                    134:     return lduw_phys(pa);
                    135: }
                    136: 
                    137: static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)
                    138: {
                    139:     target_phys_addr_t pa;
                    140:     pa = vq->vring.avail + offsetof(VRingAvail, ring[i]);
                    141:     return lduw_phys(pa);
                    142: }
                    143: 
                    144: static inline void vring_used_ring_id(VirtQueue *vq, int i, uint32_t val)
                    145: {
                    146:     target_phys_addr_t pa;
                    147:     pa = vq->vring.used + offsetof(VRingUsed, ring[i].id);
                    148:     stl_phys(pa, val);
                    149: }
                    150: 
                    151: static inline void vring_used_ring_len(VirtQueue *vq, int i, uint32_t val)
                    152: {
                    153:     target_phys_addr_t pa;
                    154:     pa = vq->vring.used + offsetof(VRingUsed, ring[i].len);
                    155:     stl_phys(pa, val);
                    156: }
                    157: 
                    158: static uint16_t vring_used_idx(VirtQueue *vq)
                    159: {
                    160:     target_phys_addr_t pa;
                    161:     pa = vq->vring.used + offsetof(VRingUsed, idx);
                    162:     return lduw_phys(pa);
                    163: }
                    164: 
                    165: static inline void vring_used_idx_increment(VirtQueue *vq, uint16_t val)
                    166: {
                    167:     target_phys_addr_t pa;
                    168:     pa = vq->vring.used + offsetof(VRingUsed, idx);
                    169:     stw_phys(pa, vring_used_idx(vq) + val);
                    170: }
                    171: 
                    172: static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask)
                    173: {
                    174:     target_phys_addr_t pa;
                    175:     pa = vq->vring.used + offsetof(VRingUsed, flags);
                    176:     stw_phys(pa, lduw_phys(pa) | mask);
                    177: }
                    178: 
                    179: static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask)
                    180: {
                    181:     target_phys_addr_t pa;
                    182:     pa = vq->vring.used + offsetof(VRingUsed, flags);
                    183:     stw_phys(pa, lduw_phys(pa) & ~mask);
                    184: }
                    185: 
                    186: void virtio_queue_set_notification(VirtQueue *vq, int enable)
                    187: {
                    188:     if (enable)
                    189:         vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
                    190:     else
                    191:         vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY);
                    192: }
                    193: 
                    194: int virtio_queue_ready(VirtQueue *vq)
                    195: {
                    196:     return vq->vring.avail != 0;
                    197: }
                    198: 
                    199: int virtio_queue_empty(VirtQueue *vq)
                    200: {
                    201:     return vring_avail_idx(vq) == vq->last_avail_idx;
                    202: }
                    203: 
                    204: void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
                    205:                     unsigned int len, unsigned int idx)
                    206: {
                    207:     unsigned int offset;
                    208:     int i;
                    209: 
1.1.1.8 ! root      210:     trace_virtqueue_fill(vq, elem, len, idx);
        !           211: 
1.1       root      212:     offset = 0;
                    213:     for (i = 0; i < elem->in_num; i++) {
                    214:         size_t size = MIN(len - offset, elem->in_sg[i].iov_len);
                    215: 
1.1.1.5   root      216:         cpu_physical_memory_unmap(elem->in_sg[i].iov_base,
                    217:                                   elem->in_sg[i].iov_len,
                    218:                                   1, size);
1.1       root      219: 
1.1.1.5   root      220:         offset += elem->in_sg[i].iov_len;
1.1       root      221:     }
                    222: 
1.1.1.5   root      223:     for (i = 0; i < elem->out_num; i++)
                    224:         cpu_physical_memory_unmap(elem->out_sg[i].iov_base,
                    225:                                   elem->out_sg[i].iov_len,
                    226:                                   0, elem->out_sg[i].iov_len);
                    227: 
1.1       root      228:     idx = (idx + vring_used_idx(vq)) % vq->vring.num;
                    229: 
                    230:     /* Get a pointer to the next entry in the used ring. */
                    231:     vring_used_ring_id(vq, idx, elem->index);
                    232:     vring_used_ring_len(vq, idx, len);
                    233: }
                    234: 
                    235: void virtqueue_flush(VirtQueue *vq, unsigned int count)
                    236: {
                    237:     /* Make sure buffer is written before we update index. */
                    238:     wmb();
1.1.1.8 ! root      239:     trace_virtqueue_flush(vq, count);
1.1       root      240:     vring_used_idx_increment(vq, count);
                    241:     vq->inuse -= count;
                    242: }
                    243: 
                    244: void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
                    245:                     unsigned int len)
                    246: {
                    247:     virtqueue_fill(vq, elem, len, 0);
                    248:     virtqueue_flush(vq, 1);
                    249: }
                    250: 
                    251: static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
                    252: {
                    253:     uint16_t num_heads = vring_avail_idx(vq) - idx;
                    254: 
                    255:     /* Check it isn't doing very strange things with descriptor numbers. */
                    256:     if (num_heads > vq->vring.num) {
1.1.1.8 ! root      257:         error_report("Guest moved used index from %u to %u",
        !           258:                      idx, vring_avail_idx(vq));
1.1       root      259:         exit(1);
                    260:     }
                    261: 
                    262:     return num_heads;
                    263: }
                    264: 
                    265: static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
                    266: {
                    267:     unsigned int head;
                    268: 
                    269:     /* Grab the next descriptor number they're advertising, and increment
                    270:      * the index we've seen. */
                    271:     head = vring_avail_ring(vq, idx % vq->vring.num);
                    272: 
                    273:     /* If their number is silly, that's a fatal mistake. */
                    274:     if (head >= vq->vring.num) {
1.1.1.8 ! root      275:         error_report("Guest says index %u is available", head);
1.1       root      276:         exit(1);
                    277:     }
                    278: 
                    279:     return head;
                    280: }
                    281: 
1.1.1.5   root      282: static unsigned virtqueue_next_desc(target_phys_addr_t desc_pa,
                    283:                                     unsigned int i, unsigned int max)
1.1       root      284: {
                    285:     unsigned int next;
                    286: 
                    287:     /* If this descriptor says it doesn't chain, we're done. */
1.1.1.5   root      288:     if (!(vring_desc_flags(desc_pa, i) & VRING_DESC_F_NEXT))
                    289:         return max;
1.1       root      290: 
                    291:     /* Check they're not leading us off end of descriptors. */
1.1.1.5   root      292:     next = vring_desc_next(desc_pa, i);
1.1       root      293:     /* Make sure compiler knows to grab that: we don't want it changing! */
                    294:     wmb();
                    295: 
1.1.1.5   root      296:     if (next >= max) {
1.1.1.8 ! root      297:         error_report("Desc next is %u", next);
1.1       root      298:         exit(1);
                    299:     }
                    300: 
                    301:     return next;
                    302: }
                    303: 
                    304: int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
                    305: {
                    306:     unsigned int idx;
1.1.1.5   root      307:     int total_bufs, in_total, out_total;
1.1       root      308: 
                    309:     idx = vq->last_avail_idx;
                    310: 
1.1.1.5   root      311:     total_bufs = in_total = out_total = 0;
1.1       root      312:     while (virtqueue_num_heads(vq, idx)) {
1.1.1.5   root      313:         unsigned int max, num_bufs, indirect = 0;
                    314:         target_phys_addr_t desc_pa;
1.1       root      315:         int i;
                    316: 
1.1.1.5   root      317:         max = vq->vring.num;
                    318:         num_bufs = total_bufs;
1.1       root      319:         i = virtqueue_get_head(vq, idx++);
1.1.1.5   root      320:         desc_pa = vq->vring.desc;
                    321: 
                    322:         if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) {
                    323:             if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) {
1.1.1.8 ! root      324:                 error_report("Invalid size for indirect buffer table");
1.1.1.5   root      325:                 exit(1);
                    326:             }
                    327: 
                    328:             /* If we've got too many, that implies a descriptor loop. */
                    329:             if (num_bufs >= max) {
1.1.1.8 ! root      330:                 error_report("Looped descriptor");
1.1.1.5   root      331:                 exit(1);
                    332:             }
                    333: 
                    334:             /* loop over the indirect descriptor table */
                    335:             indirect = 1;
                    336:             max = vring_desc_len(desc_pa, i) / sizeof(VRingDesc);
                    337:             num_bufs = i = 0;
                    338:             desc_pa = vring_desc_addr(desc_pa, i);
                    339:         }
                    340: 
1.1       root      341:         do {
                    342:             /* If we've got too many, that implies a descriptor loop. */
1.1.1.5   root      343:             if (++num_bufs > max) {
1.1.1.8 ! root      344:                 error_report("Looped descriptor");
1.1       root      345:                 exit(1);
                    346:             }
                    347: 
1.1.1.5   root      348:             if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
1.1       root      349:                 if (in_bytes > 0 &&
1.1.1.5   root      350:                     (in_total += vring_desc_len(desc_pa, i)) >= in_bytes)
1.1       root      351:                     return 1;
                    352:             } else {
                    353:                 if (out_bytes > 0 &&
1.1.1.5   root      354:                     (out_total += vring_desc_len(desc_pa, i)) >= out_bytes)
1.1       root      355:                     return 1;
                    356:             }
1.1.1.5   root      357:         } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
                    358: 
                    359:         if (!indirect)
                    360:             total_bufs = num_bufs;
                    361:         else
                    362:             total_bufs++;
1.1       root      363:     }
                    364: 
                    365:     return 0;
                    366: }
                    367: 
1.1.1.7   root      368: void virtqueue_map_sg(struct iovec *sg, target_phys_addr_t *addr,
                    369:     size_t num_sg, int is_write)
                    370: {
                    371:     unsigned int i;
                    372:     target_phys_addr_t len;
                    373: 
                    374:     for (i = 0; i < num_sg; i++) {
                    375:         len = sg[i].iov_len;
                    376:         sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
                    377:         if (sg[i].iov_base == NULL || len != sg[i].iov_len) {
1.1.1.8 ! root      378:             error_report("virtio: trying to map MMIO memory");
1.1.1.7   root      379:             exit(1);
                    380:         }
                    381:     }
                    382: }
                    383: 
1.1       root      384: int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
                    385: {
1.1.1.5   root      386:     unsigned int i, head, max;
                    387:     target_phys_addr_t desc_pa = vq->vring.desc;
1.1       root      388: 
                    389:     if (!virtqueue_num_heads(vq, vq->last_avail_idx))
                    390:         return 0;
                    391: 
                    392:     /* When we start there are none of either input nor output. */
                    393:     elem->out_num = elem->in_num = 0;
                    394: 
1.1.1.5   root      395:     max = vq->vring.num;
                    396: 
1.1       root      397:     i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
1.1.1.5   root      398: 
                    399:     if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) {
                    400:         if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) {
1.1.1.8 ! root      401:             error_report("Invalid size for indirect buffer table");
1.1.1.5   root      402:             exit(1);
                    403:         }
                    404: 
                    405:         /* loop over the indirect descriptor table */
                    406:         max = vring_desc_len(desc_pa, i) / sizeof(VRingDesc);
                    407:         desc_pa = vring_desc_addr(desc_pa, i);
                    408:         i = 0;
                    409:     }
                    410: 
1.1.1.7   root      411:     /* Collect all the descriptors */
1.1       root      412:     do {
                    413:         struct iovec *sg;
                    414: 
1.1.1.5   root      415:         if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
                    416:             elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
1.1       root      417:             sg = &elem->in_sg[elem->in_num++];
1.1.1.7   root      418:         } else {
                    419:             elem->out_addr[elem->out_num] = vring_desc_addr(desc_pa, i);
1.1       root      420:             sg = &elem->out_sg[elem->out_num++];
1.1.1.7   root      421:         }
1.1       root      422: 
1.1.1.5   root      423:         sg->iov_len = vring_desc_len(desc_pa, i);
1.1       root      424: 
                    425:         /* If we've got too many, that implies a descriptor loop. */
1.1.1.5   root      426:         if ((elem->in_num + elem->out_num) > max) {
1.1.1.8 ! root      427:             error_report("Looped descriptor");
1.1       root      428:             exit(1);
                    429:         }
1.1.1.5   root      430:     } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
1.1       root      431: 
1.1.1.7   root      432:     /* Now map what we have collected */
                    433:     virtqueue_map_sg(elem->in_sg, elem->in_addr, elem->in_num, 1);
                    434:     virtqueue_map_sg(elem->out_sg, elem->out_addr, elem->out_num, 0);
                    435: 
1.1       root      436:     elem->index = head;
                    437: 
                    438:     vq->inuse++;
                    439: 
1.1.1.8 ! root      440:     trace_virtqueue_pop(vq, elem, elem->in_num, elem->out_num);
1.1       root      441:     return elem->in_num + elem->out_num;
                    442: }
                    443: 
                    444: /* virtio device */
1.1.1.5   root      445: static void virtio_notify_vector(VirtIODevice *vdev, uint16_t vector)
1.1       root      446: {
1.1.1.5   root      447:     if (vdev->binding->notify) {
                    448:         vdev->binding->notify(vdev->binding_opaque, vector);
                    449:     }
1.1       root      450: }
                    451: 
1.1.1.5   root      452: void virtio_update_irq(VirtIODevice *vdev)
1.1       root      453: {
1.1.1.5   root      454:     virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);
1.1       root      455: }
                    456: 
1.1.1.5   root      457: void virtio_reset(void *opaque)
1.1       root      458: {
                    459:     VirtIODevice *vdev = opaque;
                    460:     int i;
                    461: 
1.1.1.7   root      462:     virtio_set_status(vdev, 0);
                    463: 
1.1       root      464:     if (vdev->reset)
                    465:         vdev->reset(vdev);
                    466: 
1.1.1.7   root      467:     vdev->guest_features = 0;
1.1       root      468:     vdev->queue_sel = 0;
                    469:     vdev->status = 0;
                    470:     vdev->isr = 0;
1.1.1.5   root      471:     vdev->config_vector = VIRTIO_NO_VECTOR;
                    472:     virtio_notify_vector(vdev, vdev->config_vector);
1.1       root      473: 
                    474:     for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
                    475:         vdev->vq[i].vring.desc = 0;
                    476:         vdev->vq[i].vring.avail = 0;
                    477:         vdev->vq[i].vring.used = 0;
                    478:         vdev->vq[i].last_avail_idx = 0;
1.1.1.5   root      479:         vdev->vq[i].pa = 0;
                    480:         vdev->vq[i].vector = VIRTIO_NO_VECTOR;
1.1       root      481:     }
                    482: }
                    483: 
1.1.1.5   root      484: uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr)
1.1       root      485: {
                    486:     uint8_t val;
                    487: 
                    488:     vdev->get_config(vdev, vdev->config);
                    489: 
                    490:     if (addr > (vdev->config_len - sizeof(val)))
                    491:         return (uint32_t)-1;
                    492: 
                    493:     memcpy(&val, vdev->config + addr, sizeof(val));
                    494:     return val;
                    495: }
                    496: 
1.1.1.5   root      497: uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr)
1.1       root      498: {
                    499:     uint16_t val;
                    500: 
                    501:     vdev->get_config(vdev, vdev->config);
                    502: 
                    503:     if (addr > (vdev->config_len - sizeof(val)))
                    504:         return (uint32_t)-1;
                    505: 
                    506:     memcpy(&val, vdev->config + addr, sizeof(val));
                    507:     return val;
                    508: }
                    509: 
1.1.1.5   root      510: uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr)
1.1       root      511: {
                    512:     uint32_t val;
                    513: 
                    514:     vdev->get_config(vdev, vdev->config);
                    515: 
                    516:     if (addr > (vdev->config_len - sizeof(val)))
                    517:         return (uint32_t)-1;
                    518: 
                    519:     memcpy(&val, vdev->config + addr, sizeof(val));
                    520:     return val;
                    521: }
                    522: 
1.1.1.5   root      523: void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data)
1.1       root      524: {
                    525:     uint8_t val = data;
                    526: 
                    527:     if (addr > (vdev->config_len - sizeof(val)))
                    528:         return;
                    529: 
                    530:     memcpy(vdev->config + addr, &val, sizeof(val));
                    531: 
                    532:     if (vdev->set_config)
                    533:         vdev->set_config(vdev, vdev->config);
                    534: }
                    535: 
1.1.1.5   root      536: void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data)
1.1       root      537: {
                    538:     uint16_t val = data;
                    539: 
                    540:     if (addr > (vdev->config_len - sizeof(val)))
                    541:         return;
                    542: 
                    543:     memcpy(vdev->config + addr, &val, sizeof(val));
                    544: 
                    545:     if (vdev->set_config)
                    546:         vdev->set_config(vdev, vdev->config);
                    547: }
                    548: 
1.1.1.5   root      549: void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data)
1.1       root      550: {
                    551:     uint32_t val = data;
                    552: 
                    553:     if (addr > (vdev->config_len - sizeof(val)))
                    554:         return;
                    555: 
                    556:     memcpy(vdev->config + addr, &val, sizeof(val));
                    557: 
                    558:     if (vdev->set_config)
                    559:         vdev->set_config(vdev, vdev->config);
                    560: }
                    561: 
1.1.1.5   root      562: void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr)
1.1       root      563: {
1.1.1.5   root      564:     vdev->vq[n].pa = addr;
                    565:     virtqueue_init(&vdev->vq[n]);
                    566: }
                    567: 
                    568: target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n)
                    569: {
                    570:     return vdev->vq[n].pa;
                    571: }
1.1       root      572: 
1.1.1.5   root      573: int virtio_queue_get_num(VirtIODevice *vdev, int n)
                    574: {
                    575:     return vdev->vq[n].vring.num;
                    576: }
1.1       root      577: 
1.1.1.8 ! root      578: void virtio_queue_notify_vq(VirtQueue *vq)
        !           579: {
        !           580:     if (vq->vring.desc) {
        !           581:         VirtIODevice *vdev = vq->vdev;
        !           582:         trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
        !           583:         vq->handle_output(vdev, vq);
        !           584:     }
        !           585: }
        !           586: 
1.1.1.5   root      587: void virtio_queue_notify(VirtIODevice *vdev, int n)
                    588: {
1.1.1.8 ! root      589:     if (n < VIRTIO_PCI_QUEUE_MAX) {
        !           590:         virtio_queue_notify_vq(&vdev->vq[n]);
1.1       root      591:     }
                    592: }
                    593: 
1.1.1.5   root      594: uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
                    595: {
                    596:     return n < VIRTIO_PCI_QUEUE_MAX ? vdev->vq[n].vector :
                    597:         VIRTIO_NO_VECTOR;
                    598: }
                    599: 
                    600: void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector)
                    601: {
                    602:     if (n < VIRTIO_PCI_QUEUE_MAX)
                    603:         vdev->vq[n].vector = vector;
                    604: }
                    605: 
1.1       root      606: VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
                    607:                             void (*handle_output)(VirtIODevice *, VirtQueue *))
                    608: {
                    609:     int i;
                    610: 
                    611:     for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
                    612:         if (vdev->vq[i].vring.num == 0)
                    613:             break;
                    614:     }
                    615: 
                    616:     if (i == VIRTIO_PCI_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)
                    617:         abort();
                    618: 
                    619:     vdev->vq[i].vring.num = queue_size;
                    620:     vdev->vq[i].handle_output = handle_output;
                    621: 
                    622:     return &vdev->vq[i];
                    623: }
                    624: 
1.1.1.7   root      625: void virtio_irq(VirtQueue *vq)
                    626: {
1.1.1.8 ! root      627:     trace_virtio_irq(vq);
1.1.1.7   root      628:     vq->vdev->isr |= 0x01;
                    629:     virtio_notify_vector(vq->vdev, vq->vector);
                    630: }
                    631: 
1.1       root      632: void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
                    633: {
1.1.1.2   root      634:     /* Always notify when queue is empty (when feature acknowledge) */
                    635:     if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) &&
1.1.1.7   root      636:         (!(vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
1.1.1.2   root      637:          (vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
1.1       root      638:         return;
                    639: 
1.1.1.8 ! root      640:     trace_virtio_notify(vdev, vq);
1.1       root      641:     vdev->isr |= 0x01;
1.1.1.5   root      642:     virtio_notify_vector(vdev, vq->vector);
1.1       root      643: }
                    644: 
                    645: void virtio_notify_config(VirtIODevice *vdev)
                    646: {
                    647:     if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
                    648:         return;
                    649: 
                    650:     vdev->isr |= 0x03;
1.1.1.5   root      651:     virtio_notify_vector(vdev, vdev->config_vector);
1.1       root      652: }
                    653: 
                    654: void virtio_save(VirtIODevice *vdev, QEMUFile *f)
                    655: {
                    656:     int i;
                    657: 
1.1.1.5   root      658:     if (vdev->binding->save_config)
                    659:         vdev->binding->save_config(vdev->binding_opaque, f);
1.1       root      660: 
                    661:     qemu_put_8s(f, &vdev->status);
                    662:     qemu_put_8s(f, &vdev->isr);
                    663:     qemu_put_be16s(f, &vdev->queue_sel);
1.1.1.7   root      664:     qemu_put_be32s(f, &vdev->guest_features);
1.1       root      665:     qemu_put_be32(f, vdev->config_len);
                    666:     qemu_put_buffer(f, vdev->config, vdev->config_len);
                    667: 
                    668:     for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
                    669:         if (vdev->vq[i].vring.num == 0)
                    670:             break;
                    671:     }
                    672: 
                    673:     qemu_put_be32(f, i);
                    674: 
                    675:     for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
                    676:         if (vdev->vq[i].vring.num == 0)
                    677:             break;
                    678: 
                    679:         qemu_put_be32(f, vdev->vq[i].vring.num);
1.1.1.5   root      680:         qemu_put_be64(f, vdev->vq[i].pa);
1.1       root      681:         qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
1.1.1.5   root      682:         if (vdev->binding->save_queue)
                    683:             vdev->binding->save_queue(vdev->binding_opaque, i, f);
1.1       root      684:     }
                    685: }
                    686: 
1.1.1.5   root      687: int virtio_load(VirtIODevice *vdev, QEMUFile *f)
1.1       root      688: {
1.1.1.5   root      689:     int num, i, ret;
1.1.1.6   root      690:     uint32_t features;
1.1.1.7   root      691:     uint32_t supported_features =
1.1.1.6   root      692:         vdev->binding->get_features(vdev->binding_opaque);
1.1       root      693: 
1.1.1.5   root      694:     if (vdev->binding->load_config) {
                    695:         ret = vdev->binding->load_config(vdev->binding_opaque, f);
                    696:         if (ret)
                    697:             return ret;
                    698:     }
1.1       root      699: 
                    700:     qemu_get_8s(f, &vdev->status);
                    701:     qemu_get_8s(f, &vdev->isr);
                    702:     qemu_get_be16s(f, &vdev->queue_sel);
1.1.1.6   root      703:     qemu_get_be32s(f, &features);
                    704:     if (features & ~supported_features) {
1.1.1.8 ! root      705:         error_report("Features 0x%x unsupported. Allowed features: 0x%x",
        !           706:                      features, supported_features);
1.1.1.6   root      707:         return -1;
                    708:     }
1.1.1.7   root      709:     if (vdev->set_features)
                    710:         vdev->set_features(vdev, features);
                    711:     vdev->guest_features = features;
1.1       root      712:     vdev->config_len = qemu_get_be32(f);
                    713:     qemu_get_buffer(f, vdev->config, vdev->config_len);
                    714: 
                    715:     num = qemu_get_be32(f);
                    716: 
                    717:     for (i = 0; i < num; i++) {
                    718:         vdev->vq[i].vring.num = qemu_get_be32(f);
1.1.1.5   root      719:         vdev->vq[i].pa = qemu_get_be64(f);
1.1       root      720:         qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
                    721: 
1.1.1.5   root      722:         if (vdev->vq[i].pa) {
1.1.1.8 ! root      723:             uint16_t nheads;
1.1.1.5   root      724:             virtqueue_init(&vdev->vq[i]);
1.1.1.8 ! root      725:             nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;
        !           726:             /* Check it isn't doing very strange things with descriptor numbers. */
        !           727:             if (nheads > vdev->vq[i].vring.num) {
        !           728:                 error_report("VQ %d size 0x%x Guest index 0x%x "
        !           729:                              "inconsistent with Host index 0x%x: delta 0x%x\n",
        !           730:                              i, vdev->vq[i].vring.num,
        !           731:                              vring_avail_idx(&vdev->vq[i]),
        !           732:                              vdev->vq[i].last_avail_idx, nheads);
        !           733:                 return -1;
        !           734:             }
        !           735:         } else if (vdev->vq[i].last_avail_idx) {
        !           736:             error_report("VQ %d address 0x0 "
        !           737:                          "inconsistent with Host index 0x%x\n",
        !           738:                          i, vdev->vq[i].last_avail_idx);
        !           739:                 return -1;
        !           740:        }
1.1.1.5   root      741:         if (vdev->binding->load_queue) {
                    742:             ret = vdev->binding->load_queue(vdev->binding_opaque, i, f);
                    743:             if (ret)
                    744:                 return ret;
1.1       root      745:         }
                    746:     }
                    747: 
1.1.1.5   root      748:     virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);
                    749:     return 0;
1.1       root      750: }
                    751: 
1.1.1.4   root      752: void virtio_cleanup(VirtIODevice *vdev)
                    753: {
1.1.1.8 ! root      754:     qemu_del_vm_change_state_handler(vdev->vmstate);
1.1.1.4   root      755:     if (vdev->config)
                    756:         qemu_free(vdev->config);
                    757:     qemu_free(vdev->vq);
                    758: }
                    759: 
1.1.1.8 ! root      760: static void virtio_vmstate_change(void *opaque, int running, int reason)
        !           761: {
        !           762:     VirtIODevice *vdev = opaque;
        !           763:     bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
        !           764:     vdev->vm_running = running;
        !           765: 
        !           766:     if (backend_run) {
        !           767:         virtio_set_status(vdev, vdev->status);
        !           768:     }
        !           769: 
        !           770:     if (vdev->binding->vmstate_change) {
        !           771:         vdev->binding->vmstate_change(vdev->binding_opaque, backend_run);
        !           772:     }
        !           773: 
        !           774:     if (!backend_run) {
        !           775:         virtio_set_status(vdev, vdev->status);
        !           776:     }
        !           777: }
        !           778: 
1.1.1.5   root      779: VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
                    780:                                  size_t config_size, size_t struct_size)
1.1       root      781: {
                    782:     VirtIODevice *vdev;
1.1.1.6   root      783:     int i;
1.1       root      784: 
1.1.1.5   root      785:     vdev = qemu_mallocz(struct_size);
1.1       root      786: 
1.1.1.5   root      787:     vdev->device_id = device_id;
1.1       root      788:     vdev->status = 0;
                    789:     vdev->isr = 0;
                    790:     vdev->queue_sel = 0;
1.1.1.5   root      791:     vdev->config_vector = VIRTIO_NO_VECTOR;
1.1       root      792:     vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
1.1.1.7   root      793:     for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
1.1.1.6   root      794:         vdev->vq[i].vector = VIRTIO_NO_VECTOR;
1.1.1.7   root      795:         vdev->vq[i].vdev = vdev;
                    796:     }
1.1       root      797: 
                    798:     vdev->name = name;
                    799:     vdev->config_len = config_size;
                    800:     if (vdev->config_len)
                    801:         vdev->config = qemu_mallocz(config_size);
                    802:     else
                    803:         vdev->config = NULL;
                    804: 
1.1.1.8 ! root      805:     vdev->vmstate = qemu_add_vm_change_state_handler(virtio_vmstate_change, vdev);
        !           806: 
1.1       root      807:     return vdev;
                    808: }
1.1.1.5   root      809: 
                    810: void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
                    811:                         void *opaque)
                    812: {
                    813:     vdev->binding = binding;
                    814:     vdev->binding_opaque = opaque;
                    815: }
1.1.1.7   root      816: 
                    817: target_phys_addr_t virtio_queue_get_desc_addr(VirtIODevice *vdev, int n)
                    818: {
                    819:     return vdev->vq[n].vring.desc;
                    820: }
                    821: 
                    822: target_phys_addr_t virtio_queue_get_avail_addr(VirtIODevice *vdev, int n)
                    823: {
                    824:     return vdev->vq[n].vring.avail;
                    825: }
                    826: 
                    827: target_phys_addr_t virtio_queue_get_used_addr(VirtIODevice *vdev, int n)
                    828: {
                    829:     return vdev->vq[n].vring.used;
                    830: }
                    831: 
                    832: target_phys_addr_t virtio_queue_get_ring_addr(VirtIODevice *vdev, int n)
                    833: {
                    834:     return vdev->vq[n].vring.desc;
                    835: }
                    836: 
                    837: target_phys_addr_t virtio_queue_get_desc_size(VirtIODevice *vdev, int n)
                    838: {
                    839:     return sizeof(VRingDesc) * vdev->vq[n].vring.num;
                    840: }
                    841: 
                    842: target_phys_addr_t virtio_queue_get_avail_size(VirtIODevice *vdev, int n)
                    843: {
                    844:     return offsetof(VRingAvail, ring) +
                    845:         sizeof(uint64_t) * vdev->vq[n].vring.num;
                    846: }
                    847: 
                    848: target_phys_addr_t virtio_queue_get_used_size(VirtIODevice *vdev, int n)
                    849: {
                    850:     return offsetof(VRingUsed, ring) +
                    851:         sizeof(VRingUsedElem) * vdev->vq[n].vring.num;
                    852: }
                    853: 
                    854: target_phys_addr_t virtio_queue_get_ring_size(VirtIODevice *vdev, int n)
                    855: {
                    856:     return vdev->vq[n].vring.used - vdev->vq[n].vring.desc +
                    857:            virtio_queue_get_used_size(vdev, n);
                    858: }
                    859: 
                    860: uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n)
                    861: {
                    862:     return vdev->vq[n].last_avail_idx;
                    863: }
                    864: 
                    865: void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx)
                    866: {
                    867:     vdev->vq[n].last_avail_idx = idx;
                    868: }
                    869: 
                    870: VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n)
                    871: {
                    872:     return vdev->vq + n;
                    873: }
                    874: 
                    875: EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq)
                    876: {
                    877:     return &vq->guest_notifier;
                    878: }
                    879: EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq)
                    880: {
                    881:     return &vq->host_notifier;
                    882: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.