uint16_t vector;
VirtIOHandleOutput handle_output;
- VirtIOHandleAIOOutput handle_aio_output;
VirtIODevice *vdev;
EventNotifier guest_notifier;
EventNotifier host_notifier;
hwaddr off_off = offsetof(VRingPackedDescEvent, off_wrap);
hwaddr off_flags = offsetof(VRingPackedDescEvent, flags);
- address_space_read_cached(cache, off_flags, &e->flags,
- sizeof(e->flags));
+ e->flags = virtio_lduw_phys_cached(vdev, cache, off_flags);
/* Make sure flags is seen before off_wrap */
smp_rmb();
- address_space_read_cached(cache, off_off, &e->off_wrap,
- sizeof(e->off_wrap));
- virtio_tswap16s(vdev, &e->off_wrap);
+ e->off_wrap = virtio_lduw_phys_cached(vdev, cache, off_off);
virtio_tswap16s(vdev, &e->flags);
}
{
hwaddr off = offsetof(VRingPackedDescEvent, off_wrap);
- virtio_tswap16s(vdev, &off_wrap);
- address_space_write_cached(cache, off, &off_wrap, sizeof(off_wrap));
+ virtio_stw_phys_cached(vdev, cache, off, off_wrap);
address_space_cache_invalidate(cache, off, sizeof(off_wrap));
}
{
hwaddr off = offsetof(VRingPackedDescEvent, flags);
- virtio_tswap16s(vdev, &flags);
- address_space_write_cached(cache, off, &flags, sizeof(flags));
+ virtio_stw_phys_cached(vdev, cache, off, flags);
address_space_cache_invalidate(cache, off, sizeof(flags));
}
MemoryRegionCache *cache,
int i)
{
- address_space_read_cached(cache,
- i * sizeof(VRingPackedDesc) +
- offsetof(VRingPackedDesc, flags),
- flags, sizeof(*flags));
- virtio_tswap16s(vdev, flags);
+ hwaddr off = i * sizeof(VRingPackedDesc) + offsetof(VRingPackedDesc, flags);
+
+ *flags = virtio_lduw_phys_cached(vdev, cache, off);
}
static void vring_packed_desc_read(VirtIODevice *vdev,
{
hwaddr off = i * sizeof(VRingPackedDesc) + offsetof(VRingPackedDesc, flags);
- virtio_tswap16s(vdev, &desc->flags);
- address_space_write_cached(cache, off, &desc->flags, sizeof(desc->flags));
+ virtio_stw_phys_cached(vdev, cache, off, desc->flags);
address_space_cache_invalidate(cache, off, sizeof(desc->flags));
}
if (vq->used_idx >= vq->vring.num) {
vq->used_idx -= vq->vring.num;
vq->used_wrap_counter ^= 1;
+ vq->signalled_used_valid = false;
}
}
return VIRTQUEUE_READ_DESC_MORE;
}
+/* Called within rcu_read_lock(). */
static void virtqueue_split_get_avail_bytes(VirtQueue *vq,
unsigned int *in_bytes, unsigned int *out_bytes,
- unsigned max_in_bytes, unsigned max_out_bytes)
+ unsigned max_in_bytes, unsigned max_out_bytes,
+ VRingMemoryRegionCaches *caches)
{
VirtIODevice *vdev = vq->vdev;
unsigned int max, idx;
unsigned int total_bufs, in_total, out_total;
- VRingMemoryRegionCaches *caches;
MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID;
int64_t len = 0;
int rc;
- RCU_READ_LOCK_GUARD();
-
idx = vq->last_avail_idx;
total_bufs = in_total = out_total = 0;
max = vq->vring.num;
- caches = vring_get_region_caches(vq);
- if (!caches) {
- goto err;
- }
while ((rc = virtqueue_num_heads(vq, idx)) > 0) {
MemoryRegionCache *desc_cache = &caches->desc;
return VIRTQUEUE_READ_DESC_MORE;
}
+/* Called within rcu_read_lock(). */
static void virtqueue_packed_get_avail_bytes(VirtQueue *vq,
unsigned int *in_bytes,
unsigned int *out_bytes,
unsigned max_in_bytes,
- unsigned max_out_bytes)
+ unsigned max_out_bytes,
+ VRingMemoryRegionCaches *caches)
{
VirtIODevice *vdev = vq->vdev;
unsigned int max, idx;
unsigned int total_bufs, in_total, out_total;
MemoryRegionCache *desc_cache;
- VRingMemoryRegionCaches *caches;
MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID;
int64_t len = 0;
VRingPackedDesc desc;
bool wrap_counter;
- RCU_READ_LOCK_GUARD();
idx = vq->last_avail_idx;
wrap_counter = vq->last_avail_wrap_counter;
total_bufs = in_total = out_total = 0;
max = vq->vring.num;
- caches = vring_get_region_caches(vq);
- if (!caches) {
- goto err;
- }
for (;;) {
unsigned int num_bufs = total_bufs;
uint16_t desc_size;
VRingMemoryRegionCaches *caches;
+ RCU_READ_LOCK_GUARD();
+
if (unlikely(!vq->vring.desc)) {
goto err;
}
if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED)) {
virtqueue_packed_get_avail_bytes(vq, in_bytes, out_bytes,
- max_in_bytes, max_out_bytes);
+ max_in_bytes, max_out_bytes,
+ caches);
} else {
virtqueue_split_get_avail_bytes(vq, in_bytes, out_bytes,
- max_in_bytes, max_out_bytes);
+ max_in_bytes, max_out_bytes,
+ caches);
}
return;
iov[num_sg].iov_base = dma_memory_map(vdev->dma_as, pa, &len,
is_write ?
DMA_DIRECTION_FROM_DEVICE :
- DMA_DIRECTION_TO_DEVICE);
+ DMA_DIRECTION_TO_DEVICE,
+ MEMTXATTRS_UNSPECIFIED);
if (!iov[num_sg].iov_base) {
virtio_error(vdev, "virtio: bogus descriptor or out of resources");
goto out;
sg[i].iov_base = dma_memory_map(vdev->dma_as,
addr[i], &len, is_write ?
DMA_DIRECTION_FROM_DEVICE :
- DMA_DIRECTION_TO_DEVICE);
+ DMA_DIRECTION_TO_DEVICE,
+ MEMTXATTRS_UNSPECIFIED);
if (!sg[i].iov_base) {
error_report("virtio: error trying to map MMIO memory");
exit(1);
VirtIODevice *vdev = vq->vdev;
VRingPackedDesc desc;
+ RCU_READ_LOCK_GUARD();
+
caches = vring_get_region_caches(vq);
if (!caches) {
return 0;
}
}
-static bool virtio_queue_notify_aio_vq(VirtQueue *vq)
-{
- bool ret = false;
-
- if (vq->vring.desc && vq->handle_aio_output) {
- VirtIODevice *vdev = vq->vdev;
-
- trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
- ret = vq->handle_aio_output(vdev, vq);
-
- if (unlikely(vdev->start_on_kick)) {
- virtio_set_started(vdev, true);
- }
- }
-
- return ret;
-}
-
static void virtio_queue_notify_vq(VirtQueue *vq)
{
if (vq->vring.desc && vq->handle_output) {
vdev->vq[i].vring.num_default = queue_size;
vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;
vdev->vq[i].handle_output = handle_output;
- vdev->vq[i].handle_aio_output = NULL;
vdev->vq[i].used_elems = g_malloc0(sizeof(VirtQueueElement) *
queue_size);
vq->vring.num = 0;
vq->vring.num_default = 0;
vq->handle_output = NULL;
- vq->handle_aio_output = NULL;
g_free(vq->used_elems);
vq->used_elems = NULL;
virtio_virtqueue_reset_region_cache(vq);
.name = "virtio",
.version_id = 1,
.minimum_version_id = 1,
- .minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_END_OF_LIST()
},
return &vq->guest_notifier;
}
-static void virtio_queue_host_notifier_aio_read(EventNotifier *n)
-{
- VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
- if (event_notifier_test_and_clear(n)) {
- virtio_queue_notify_aio_vq(vq);
- }
-}
-
static void virtio_queue_host_notifier_aio_poll_begin(EventNotifier *n)
{
VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
EventNotifier *n = opaque;
VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
- if (!vq->vring.desc || virtio_queue_empty(vq)) {
- return false;
- }
+ return vq->vring.desc && !virtio_queue_empty(vq);
+}
+
+static void virtio_queue_host_notifier_aio_poll_ready(EventNotifier *n)
+{
+ VirtQueue *vq = container_of(n, VirtQueue, host_notifier);
- return virtio_queue_notify_aio_vq(vq);
+ virtio_queue_notify_vq(vq);
}
static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n)
virtio_queue_set_notification(vq, 1);
}
-void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx,
- VirtIOHandleAIOOutput handle_output)
+void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx)
{
- if (handle_output) {
- vq->handle_aio_output = handle_output;
- aio_set_event_notifier(ctx, &vq->host_notifier, true,
- virtio_queue_host_notifier_aio_read,
- virtio_queue_host_notifier_aio_poll);
- aio_set_event_notifier_poll(ctx, &vq->host_notifier,
- virtio_queue_host_notifier_aio_poll_begin,
- virtio_queue_host_notifier_aio_poll_end);
- } else {
- aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL, NULL);
- /* Test and clear notifier before after disabling event,
- * in case poll callback didn't have time to run. */
- virtio_queue_host_notifier_aio_read(&vq->host_notifier);
- vq->handle_aio_output = NULL;
- }
+ aio_set_event_notifier(ctx, &vq->host_notifier, true,
+ virtio_queue_host_notifier_read,
+ virtio_queue_host_notifier_aio_poll,
+ virtio_queue_host_notifier_aio_poll_ready);
+ aio_set_event_notifier_poll(ctx, &vq->host_notifier,
+ virtio_queue_host_notifier_aio_poll_begin,
+ virtio_queue_host_notifier_aio_poll_end);
+}
+
+void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx)
+{
+ aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL, NULL, NULL);
+ /* Test and clear notifier before after disabling event,
+ * in case poll callback didn't have time to run. */
+ virtio_queue_host_notifier_read(&vq->host_notifier);
}
void virtio_queue_host_notifier_read(EventNotifier *n)
}
vdev->listener.commit = virtio_memory_listener_commit;
+ vdev->listener.name = "virtio";
memory_listener_register(&vdev->listener, vdev->dma_as);
}