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

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

unix.superglobalmegacorp.com

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