static void virtio_crypto_dataq_bh(void *opaque) { VirtIOCryptoQueue *q = opaque; VirtIOCrypto *vcrypto = q->vcrypto; VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto); /* This happens when device was stopped but BH wasn't. */ if (!vdev->vm_running) { return; } /* Just in case the driver is not ready on more */ if (unlikely(!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))) { return; } for (;;) { virtio_crypto_handle_dataq(vdev, q->dataq); virtio_queue_set_notification(q->dataq, 1); /* Are we done or did the guest add more buffers? */ if (virtio_queue_empty(q->dataq)) { break; } virtio_queue_set_notification(q->dataq, 0); } }
static int do_virtio_net_can_receive(VirtIONet *n, int bufsize) { if (!virtio_queue_ready(n->rx_vq) || !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) return 0; if (virtio_queue_empty(n->rx_vq) || (n->mergeable_rx_bufs && !virtqueue_avail_bytes(n->rx_vq, bufsize, 0))) { virtio_queue_set_notification(n->rx_vq, 1); return 0; } virtio_queue_set_notification(n->rx_vq, 0); return 1; }
static int vcon_can_read(void *opaque) { VirtIOConsole *s = (VirtIOConsole *) opaque; if (!virtio_queue_ready(s->ivq) || !(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) || virtio_queue_empty(s->ivq)) return 0; /* current implementations have a page sized buffer. * We fall back to a one byte per read if there is not enough room. * It would be cool to have a function that returns the available byte * instead of checking for a limit */ if (virtqueue_avail_bytes(s->ivq, TARGET_PAGE_SIZE, 0)) return TARGET_PAGE_SIZE; if (virtqueue_avail_bytes(s->ivq, 1, 0)) return 1; return 0; }
/* Send data from a char device over to the guest */ static void chr_read(void *opaque, const void *buf, size_t size) { VirtIORNG *vrng = opaque; VirtIODevice *vdev = VIRTIO_DEVICE(vrng); VirtQueueElement *elem; size_t len; int offset; if (!is_guest_ready(vrng)) { return; } vrng->quota_remaining -= size; offset = 0; while (offset < size) { elem = virtqueue_pop(vrng->vq, sizeof(VirtQueueElement)); if (!elem) { break; } len = iov_from_buf(elem->in_sg, elem->in_num, 0, buf + offset, size - offset); offset += len; virtqueue_push(vrng->vq, elem, len); trace_virtio_rng_pushed(vrng, len); g_free(elem); } virtio_notify(vdev, vrng->vq); if (!virtio_queue_empty(vrng->vq)) { /* If we didn't drain the queue, call virtio_rng_process * to take care of asking for more data as appropriate. */ virtio_rng_process(vrng); } }