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

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);
                     76: };
                     77: 
                     78: #define VIRTIO_PCI_QUEUE_MAX        16
                     79: 
                     80: /* virt queue functions */
1.1.1.5   root       81: static void virtqueue_init(VirtQueue *vq)
1.1       root       82: {
1.1.1.5   root       83:     target_phys_addr_t pa = vq->pa;
1.1       root       84: 
                     85:     vq->vring.desc = pa;
                     86:     vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc);
                     87:     vq->vring.used = vring_align(vq->vring.avail +
                     88:                                  offsetof(VRingAvail, ring[vq->vring.num]),
                     89:                                  VIRTIO_PCI_VRING_ALIGN);
                     90: }
                     91: 
1.1.1.5   root       92: static inline uint64_t vring_desc_addr(target_phys_addr_t desc_pa, int i)
1.1       root       93: {
                     94:     target_phys_addr_t pa;
1.1.1.5   root       95:     pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr);
1.1       root       96:     return ldq_phys(pa);
                     97: }
                     98: 
1.1.1.5   root       99: static inline uint32_t vring_desc_len(target_phys_addr_t desc_pa, int i)
1.1       root      100: {
                    101:     target_phys_addr_t pa;
1.1.1.5   root      102:     pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, len);
1.1       root      103:     return ldl_phys(pa);
                    104: }
                    105: 
1.1.1.5   root      106: static inline uint16_t vring_desc_flags(target_phys_addr_t desc_pa, int i)
1.1       root      107: {
                    108:     target_phys_addr_t pa;
1.1.1.5   root      109:     pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags);
1.1       root      110:     return lduw_phys(pa);
                    111: }
                    112: 
1.1.1.5   root      113: static inline uint16_t vring_desc_next(target_phys_addr_t desc_pa, int i)
1.1       root      114: {
                    115:     target_phys_addr_t pa;
1.1.1.5   root      116:     pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, next);
1.1       root      117:     return lduw_phys(pa);
                    118: }
                    119: 
                    120: static inline uint16_t vring_avail_flags(VirtQueue *vq)
                    121: {
                    122:     target_phys_addr_t pa;
                    123:     pa = vq->vring.avail + offsetof(VRingAvail, flags);
                    124:     return lduw_phys(pa);
                    125: }
                    126: 
                    127: static inline uint16_t vring_avail_idx(VirtQueue *vq)
                    128: {
                    129:     target_phys_addr_t pa;
                    130:     pa = vq->vring.avail + offsetof(VRingAvail, idx);
                    131:     return lduw_phys(pa);
                    132: }
                    133: 
                    134: static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)
                    135: {
                    136:     target_phys_addr_t pa;
                    137:     pa = vq->vring.avail + offsetof(VRingAvail, ring[i]);
                    138:     return lduw_phys(pa);
                    139: }
                    140: 
                    141: static inline void vring_used_ring_id(VirtQueue *vq, int i, uint32_t val)
                    142: {
                    143:     target_phys_addr_t pa;
                    144:     pa = vq->vring.used + offsetof(VRingUsed, ring[i].id);
                    145:     stl_phys(pa, val);
                    146: }
                    147: 
                    148: static inline void vring_used_ring_len(VirtQueue *vq, int i, uint32_t val)
                    149: {
                    150:     target_phys_addr_t pa;
                    151:     pa = vq->vring.used + offsetof(VRingUsed, ring[i].len);
                    152:     stl_phys(pa, val);
                    153: }
                    154: 
                    155: static uint16_t vring_used_idx(VirtQueue *vq)
                    156: {
                    157:     target_phys_addr_t pa;
                    158:     pa = vq->vring.used + offsetof(VRingUsed, idx);
                    159:     return lduw_phys(pa);
                    160: }
                    161: 
                    162: static inline void vring_used_idx_increment(VirtQueue *vq, uint16_t val)
                    163: {
                    164:     target_phys_addr_t pa;
                    165:     pa = vq->vring.used + offsetof(VRingUsed, idx);
                    166:     stw_phys(pa, vring_used_idx(vq) + val);
                    167: }
                    168: 
                    169: static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask)
                    170: {
                    171:     target_phys_addr_t pa;
                    172:     pa = vq->vring.used + offsetof(VRingUsed, flags);
                    173:     stw_phys(pa, lduw_phys(pa) | mask);
                    174: }
                    175: 
                    176: static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask)
                    177: {
                    178:     target_phys_addr_t pa;
                    179:     pa = vq->vring.used + offsetof(VRingUsed, flags);
                    180:     stw_phys(pa, lduw_phys(pa) & ~mask);
                    181: }
                    182: 
                    183: void virtio_queue_set_notification(VirtQueue *vq, int enable)
                    184: {
                    185:     if (enable)
                    186:         vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
                    187:     else
                    188:         vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY);
                    189: }
                    190: 
                    191: int virtio_queue_ready(VirtQueue *vq)
                    192: {
                    193:     return vq->vring.avail != 0;
                    194: }
                    195: 
                    196: int virtio_queue_empty(VirtQueue *vq)
                    197: {
                    198:     return vring_avail_idx(vq) == vq->last_avail_idx;
                    199: }
                    200: 
                    201: void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
                    202:                     unsigned int len, unsigned int idx)
                    203: {
                    204:     unsigned int offset;
                    205:     int i;
                    206: 
                    207:     offset = 0;
                    208:     for (i = 0; i < elem->in_num; i++) {
                    209:         size_t size = MIN(len - offset, elem->in_sg[i].iov_len);
                    210: 
1.1.1.5   root      211:         cpu_physical_memory_unmap(elem->in_sg[i].iov_base,
                    212:                                   elem->in_sg[i].iov_len,
                    213:                                   1, size);
1.1       root      214: 
1.1.1.5   root      215:         offset += elem->in_sg[i].iov_len;
1.1       root      216:     }
                    217: 
1.1.1.5   root      218:     for (i = 0; i < elem->out_num; i++)
                    219:         cpu_physical_memory_unmap(elem->out_sg[i].iov_base,
                    220:                                   elem->out_sg[i].iov_len,
                    221:                                   0, elem->out_sg[i].iov_len);
                    222: 
1.1       root      223:     idx = (idx + vring_used_idx(vq)) % vq->vring.num;
                    224: 
                    225:     /* Get a pointer to the next entry in the used ring. */
                    226:     vring_used_ring_id(vq, idx, elem->index);
                    227:     vring_used_ring_len(vq, idx, len);
                    228: }
                    229: 
                    230: void virtqueue_flush(VirtQueue *vq, unsigned int count)
                    231: {
                    232:     /* Make sure buffer is written before we update index. */
                    233:     wmb();
                    234:     vring_used_idx_increment(vq, count);
                    235:     vq->inuse -= count;
                    236: }
                    237: 
                    238: void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
                    239:                     unsigned int len)
                    240: {
                    241:     virtqueue_fill(vq, elem, len, 0);
                    242:     virtqueue_flush(vq, 1);
                    243: }
                    244: 
                    245: static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
                    246: {
                    247:     uint16_t num_heads = vring_avail_idx(vq) - idx;
                    248: 
                    249:     /* Check it isn't doing very strange things with descriptor numbers. */
                    250:     if (num_heads > vq->vring.num) {
                    251:         fprintf(stderr, "Guest moved used index from %u to %u",
                    252:                 idx, vring_avail_idx(vq));
                    253:         exit(1);
                    254:     }
                    255: 
                    256:     return num_heads;
                    257: }
                    258: 
                    259: static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
                    260: {
                    261:     unsigned int head;
                    262: 
                    263:     /* Grab the next descriptor number they're advertising, and increment
                    264:      * the index we've seen. */
                    265:     head = vring_avail_ring(vq, idx % vq->vring.num);
                    266: 
                    267:     /* If their number is silly, that's a fatal mistake. */
                    268:     if (head >= vq->vring.num) {
                    269:         fprintf(stderr, "Guest says index %u is available", head);
                    270:         exit(1);
                    271:     }
                    272: 
                    273:     return head;
                    274: }
                    275: 
1.1.1.5   root      276: static unsigned virtqueue_next_desc(target_phys_addr_t desc_pa,
                    277:                                     unsigned int i, unsigned int max)
1.1       root      278: {
                    279:     unsigned int next;
                    280: 
                    281:     /* If this descriptor says it doesn't chain, we're done. */
1.1.1.5   root      282:     if (!(vring_desc_flags(desc_pa, i) & VRING_DESC_F_NEXT))
                    283:         return max;
1.1       root      284: 
                    285:     /* Check they're not leading us off end of descriptors. */
1.1.1.5   root      286:     next = vring_desc_next(desc_pa, i);
1.1       root      287:     /* Make sure compiler knows to grab that: we don't want it changing! */
                    288:     wmb();
                    289: 
1.1.1.5   root      290:     if (next >= max) {
1.1       root      291:         fprintf(stderr, "Desc next is %u", next);
                    292:         exit(1);
                    293:     }
                    294: 
                    295:     return next;
                    296: }
                    297: 
                    298: int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
                    299: {
                    300:     unsigned int idx;
1.1.1.5   root      301:     int total_bufs, in_total, out_total;
1.1       root      302: 
                    303:     idx = vq->last_avail_idx;
                    304: 
1.1.1.5   root      305:     total_bufs = in_total = out_total = 0;
1.1       root      306:     while (virtqueue_num_heads(vq, idx)) {
1.1.1.5   root      307:         unsigned int max, num_bufs, indirect = 0;
                    308:         target_phys_addr_t desc_pa;
1.1       root      309:         int i;
                    310: 
1.1.1.5   root      311:         max = vq->vring.num;
                    312:         num_bufs = total_bufs;
1.1       root      313:         i = virtqueue_get_head(vq, idx++);
1.1.1.5   root      314:         desc_pa = vq->vring.desc;
                    315: 
                    316:         if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) {
                    317:             if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) {
                    318:                 fprintf(stderr, "Invalid size for indirect buffer table\n");
                    319:                 exit(1);
                    320:             }
                    321: 
                    322:             /* If we've got too many, that implies a descriptor loop. */
                    323:             if (num_bufs >= max) {
                    324:                 fprintf(stderr, "Looped descriptor");
                    325:                 exit(1);
                    326:             }
                    327: 
                    328:             /* loop over the indirect descriptor table */
                    329:             indirect = 1;
                    330:             max = vring_desc_len(desc_pa, i) / sizeof(VRingDesc);
                    331:             num_bufs = i = 0;
                    332:             desc_pa = vring_desc_addr(desc_pa, i);
                    333:         }
                    334: 
1.1       root      335:         do {
                    336:             /* If we've got too many, that implies a descriptor loop. */
1.1.1.5   root      337:             if (++num_bufs > max) {
1.1       root      338:                 fprintf(stderr, "Looped descriptor");
                    339:                 exit(1);
                    340:             }
                    341: 
1.1.1.5   root      342:             if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
1.1       root      343:                 if (in_bytes > 0 &&
1.1.1.5   root      344:                     (in_total += vring_desc_len(desc_pa, i)) >= in_bytes)
1.1       root      345:                     return 1;
                    346:             } else {
                    347:                 if (out_bytes > 0 &&
1.1.1.5   root      348:                     (out_total += vring_desc_len(desc_pa, i)) >= out_bytes)
1.1       root      349:                     return 1;
                    350:             }
1.1.1.5   root      351:         } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
                    352: 
                    353:         if (!indirect)
                    354:             total_bufs = num_bufs;
                    355:         else
                    356:             total_bufs++;
1.1       root      357:     }
                    358: 
                    359:     return 0;
                    360: }
                    361: 
                    362: int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
                    363: {
1.1.1.5   root      364:     unsigned int i, head, max;
                    365:     target_phys_addr_t desc_pa = vq->vring.desc;
                    366:     target_phys_addr_t len;
1.1       root      367: 
                    368:     if (!virtqueue_num_heads(vq, vq->last_avail_idx))
                    369:         return 0;
                    370: 
                    371:     /* When we start there are none of either input nor output. */
                    372:     elem->out_num = elem->in_num = 0;
                    373: 
1.1.1.5   root      374:     max = vq->vring.num;
                    375: 
1.1       root      376:     i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
1.1.1.5   root      377: 
                    378:     if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_INDIRECT) {
                    379:         if (vring_desc_len(desc_pa, i) % sizeof(VRingDesc)) {
                    380:             fprintf(stderr, "Invalid size for indirect buffer table\n");
                    381:             exit(1);
                    382:         }
                    383: 
                    384:         /* loop over the indirect descriptor table */
                    385:         max = vring_desc_len(desc_pa, i) / sizeof(VRingDesc);
                    386:         desc_pa = vring_desc_addr(desc_pa, i);
                    387:         i = 0;
                    388:     }
                    389: 
1.1       root      390:     do {
                    391:         struct iovec *sg;
1.1.1.5   root      392:         int is_write = 0;
1.1       root      393: 
1.1.1.5   root      394:         if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
                    395:             elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
1.1       root      396:             sg = &elem->in_sg[elem->in_num++];
1.1.1.5   root      397:             is_write = 1;
1.1       root      398:         } else
                    399:             sg = &elem->out_sg[elem->out_num++];
                    400: 
                    401:         /* Grab the first descriptor, and check it's OK. */
1.1.1.5   root      402:         sg->iov_len = vring_desc_len(desc_pa, i);
                    403:         len = sg->iov_len;
1.1       root      404: 
1.1.1.5   root      405:         sg->iov_base = cpu_physical_memory_map(vring_desc_addr(desc_pa, i),
                    406:                                                &len, is_write);
                    407: 
                    408:         if (sg->iov_base == NULL || len != sg->iov_len) {
                    409:             fprintf(stderr, "virtio: trying to map MMIO memory\n");
1.1       root      410:             exit(1);
                    411:         }
                    412: 
                    413:         /* If we've got too many, that implies a descriptor loop. */
1.1.1.5   root      414:         if ((elem->in_num + elem->out_num) > max) {
1.1       root      415:             fprintf(stderr, "Looped descriptor");
                    416:             exit(1);
                    417:         }
1.1.1.5   root      418:     } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
1.1       root      419: 
                    420:     elem->index = head;
                    421: 
                    422:     vq->inuse++;
                    423: 
                    424:     return elem->in_num + elem->out_num;
                    425: }
                    426: 
                    427: /* virtio device */
1.1.1.5   root      428: static void virtio_notify_vector(VirtIODevice *vdev, uint16_t vector)
1.1       root      429: {
1.1.1.5   root      430:     if (vdev->binding->notify) {
                    431:         vdev->binding->notify(vdev->binding_opaque, vector);
                    432:     }
1.1       root      433: }
                    434: 
1.1.1.5   root      435: void virtio_update_irq(VirtIODevice *vdev)
1.1       root      436: {
1.1.1.5   root      437:     virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);
1.1       root      438: }
                    439: 
1.1.1.5   root      440: void virtio_reset(void *opaque)
1.1       root      441: {
                    442:     VirtIODevice *vdev = opaque;
                    443:     int i;
                    444: 
                    445:     if (vdev->reset)
                    446:         vdev->reset(vdev);
                    447: 
                    448:     vdev->features = 0;
                    449:     vdev->queue_sel = 0;
                    450:     vdev->status = 0;
                    451:     vdev->isr = 0;
1.1.1.5   root      452:     vdev->config_vector = VIRTIO_NO_VECTOR;
                    453:     virtio_notify_vector(vdev, vdev->config_vector);
1.1       root      454: 
                    455:     for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
                    456:         vdev->vq[i].vring.desc = 0;
                    457:         vdev->vq[i].vring.avail = 0;
                    458:         vdev->vq[i].vring.used = 0;
                    459:         vdev->vq[i].last_avail_idx = 0;
1.1.1.5   root      460:         vdev->vq[i].pa = 0;
                    461:         vdev->vq[i].vector = VIRTIO_NO_VECTOR;
1.1       root      462:     }
                    463: }
                    464: 
1.1.1.5   root      465: uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr)
1.1       root      466: {
                    467:     uint8_t val;
                    468: 
                    469:     vdev->get_config(vdev, vdev->config);
                    470: 
                    471:     if (addr > (vdev->config_len - sizeof(val)))
                    472:         return (uint32_t)-1;
                    473: 
                    474:     memcpy(&val, vdev->config + addr, sizeof(val));
                    475:     return val;
                    476: }
                    477: 
1.1.1.5   root      478: uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr)
1.1       root      479: {
                    480:     uint16_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_readl(VirtIODevice *vdev, uint32_t addr)
1.1       root      492: {
                    493:     uint32_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: void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data)
1.1       root      505: {
                    506:     uint8_t val = data;
                    507: 
                    508:     if (addr > (vdev->config_len - sizeof(val)))
                    509:         return;
                    510: 
                    511:     memcpy(vdev->config + addr, &val, sizeof(val));
                    512: 
                    513:     if (vdev->set_config)
                    514:         vdev->set_config(vdev, vdev->config);
                    515: }
                    516: 
1.1.1.5   root      517: void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data)
1.1       root      518: {
                    519:     uint16_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_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data)
1.1       root      531: {
                    532:     uint32_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_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr)
1.1       root      544: {
1.1.1.5   root      545:     vdev->vq[n].pa = addr;
                    546:     virtqueue_init(&vdev->vq[n]);
                    547: }
                    548: 
                    549: target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n)
                    550: {
                    551:     return vdev->vq[n].pa;
                    552: }
1.1       root      553: 
1.1.1.5   root      554: int virtio_queue_get_num(VirtIODevice *vdev, int n)
                    555: {
                    556:     return vdev->vq[n].vring.num;
                    557: }
1.1       root      558: 
1.1.1.5   root      559: void virtio_queue_notify(VirtIODevice *vdev, int n)
                    560: {
                    561:     if (n < VIRTIO_PCI_QUEUE_MAX && vdev->vq[n].vring.desc) {
                    562:         vdev->vq[n].handle_output(vdev, &vdev->vq[n]);
1.1       root      563:     }
                    564: }
                    565: 
1.1.1.5   root      566: uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
                    567: {
                    568:     return n < VIRTIO_PCI_QUEUE_MAX ? vdev->vq[n].vector :
                    569:         VIRTIO_NO_VECTOR;
                    570: }
                    571: 
                    572: void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector)
                    573: {
                    574:     if (n < VIRTIO_PCI_QUEUE_MAX)
                    575:         vdev->vq[n].vector = vector;
                    576: }
                    577: 
1.1       root      578: VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
                    579:                             void (*handle_output)(VirtIODevice *, VirtQueue *))
                    580: {
                    581:     int i;
                    582: 
                    583:     for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
                    584:         if (vdev->vq[i].vring.num == 0)
                    585:             break;
                    586:     }
                    587: 
                    588:     if (i == VIRTIO_PCI_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)
                    589:         abort();
                    590: 
                    591:     vdev->vq[i].vring.num = queue_size;
                    592:     vdev->vq[i].handle_output = handle_output;
                    593: 
                    594:     return &vdev->vq[i];
                    595: }
                    596: 
                    597: void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
                    598: {
1.1.1.2   root      599:     /* Always notify when queue is empty (when feature acknowledge) */
                    600:     if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) &&
                    601:         (!(vdev->features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
                    602:          (vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
1.1       root      603:         return;
                    604: 
                    605:     vdev->isr |= 0x01;
1.1.1.5   root      606:     virtio_notify_vector(vdev, vq->vector);
1.1       root      607: }
                    608: 
                    609: void virtio_notify_config(VirtIODevice *vdev)
                    610: {
                    611:     if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
                    612:         return;
                    613: 
                    614:     vdev->isr |= 0x03;
1.1.1.5   root      615:     virtio_notify_vector(vdev, vdev->config_vector);
1.1       root      616: }
                    617: 
                    618: void virtio_save(VirtIODevice *vdev, QEMUFile *f)
                    619: {
                    620:     int i;
                    621: 
1.1.1.5   root      622:     if (vdev->binding->save_config)
                    623:         vdev->binding->save_config(vdev->binding_opaque, f);
1.1       root      624: 
                    625:     qemu_put_8s(f, &vdev->status);
                    626:     qemu_put_8s(f, &vdev->isr);
                    627:     qemu_put_be16s(f, &vdev->queue_sel);
                    628:     qemu_put_be32s(f, &vdev->features);
                    629:     qemu_put_be32(f, vdev->config_len);
                    630:     qemu_put_buffer(f, vdev->config, vdev->config_len);
                    631: 
                    632:     for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
                    633:         if (vdev->vq[i].vring.num == 0)
                    634:             break;
                    635:     }
                    636: 
                    637:     qemu_put_be32(f, i);
                    638: 
                    639:     for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
                    640:         if (vdev->vq[i].vring.num == 0)
                    641:             break;
                    642: 
                    643:         qemu_put_be32(f, vdev->vq[i].vring.num);
1.1.1.5   root      644:         qemu_put_be64(f, vdev->vq[i].pa);
1.1       root      645:         qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
1.1.1.5   root      646:         if (vdev->binding->save_queue)
                    647:             vdev->binding->save_queue(vdev->binding_opaque, i, f);
1.1       root      648:     }
                    649: }
                    650: 
1.1.1.5   root      651: int virtio_load(VirtIODevice *vdev, QEMUFile *f)
1.1       root      652: {
1.1.1.5   root      653:     int num, i, ret;
1.1.1.6 ! root      654:     uint32_t features;
        !           655:     uint32_t supported_features = vdev->get_features(vdev) |
        !           656:         vdev->binding->get_features(vdev->binding_opaque);
1.1       root      657: 
1.1.1.5   root      658:     if (vdev->binding->load_config) {
                    659:         ret = vdev->binding->load_config(vdev->binding_opaque, f);
                    660:         if (ret)
                    661:             return ret;
                    662:     }
1.1       root      663: 
                    664:     qemu_get_8s(f, &vdev->status);
                    665:     qemu_get_8s(f, &vdev->isr);
                    666:     qemu_get_be16s(f, &vdev->queue_sel);
1.1.1.6 ! root      667:     qemu_get_be32s(f, &features);
        !           668:     if (features & ~supported_features) {
        !           669:         fprintf(stderr, "Features 0x%x unsupported. Allowed features: 0x%x\n",
        !           670:                 features, supported_features);
        !           671:         return -1;
        !           672:     }
        !           673:     vdev->features = features;
1.1       root      674:     vdev->config_len = qemu_get_be32(f);
                    675:     qemu_get_buffer(f, vdev->config, vdev->config_len);
                    676: 
                    677:     num = qemu_get_be32(f);
                    678: 
                    679:     for (i = 0; i < num; i++) {
                    680:         vdev->vq[i].vring.num = qemu_get_be32(f);
1.1.1.5   root      681:         vdev->vq[i].pa = qemu_get_be64(f);
1.1       root      682:         qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
                    683: 
1.1.1.5   root      684:         if (vdev->vq[i].pa) {
                    685:             virtqueue_init(&vdev->vq[i]);
                    686:         }
                    687:         if (vdev->binding->load_queue) {
                    688:             ret = vdev->binding->load_queue(vdev->binding_opaque, i, f);
                    689:             if (ret)
                    690:                 return ret;
1.1       root      691:         }
                    692:     }
                    693: 
1.1.1.5   root      694:     virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);
                    695:     return 0;
1.1       root      696: }
                    697: 
1.1.1.4   root      698: void virtio_cleanup(VirtIODevice *vdev)
                    699: {
                    700:     if (vdev->config)
                    701:         qemu_free(vdev->config);
                    702:     qemu_free(vdev->vq);
                    703: }
                    704: 
1.1.1.5   root      705: VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
                    706:                                  size_t config_size, size_t struct_size)
1.1       root      707: {
                    708:     VirtIODevice *vdev;
1.1.1.6 ! root      709:     int i;
1.1       root      710: 
1.1.1.5   root      711:     vdev = qemu_mallocz(struct_size);
1.1       root      712: 
1.1.1.5   root      713:     vdev->device_id = device_id;
1.1       root      714:     vdev->status = 0;
                    715:     vdev->isr = 0;
                    716:     vdev->queue_sel = 0;
1.1.1.5   root      717:     vdev->config_vector = VIRTIO_NO_VECTOR;
1.1       root      718:     vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
1.1.1.6 ! root      719:     for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++)
        !           720:         vdev->vq[i].vector = VIRTIO_NO_VECTOR;
1.1       root      721: 
                    722:     vdev->name = name;
                    723:     vdev->config_len = config_size;
                    724:     if (vdev->config_len)
                    725:         vdev->config = qemu_mallocz(config_size);
                    726:     else
                    727:         vdev->config = NULL;
                    728: 
                    729:     return vdev;
                    730: }
1.1.1.5   root      731: 
                    732: void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
                    733:                         void *opaque)
                    734: {
                    735:     vdev->binding = binding;
                    736:     vdev->binding_opaque = opaque;
                    737: }

unix.superglobalmegacorp.com

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