19
#include "exec/memory.h"
20
#include "exec/address-spaces.h"
18
21
#include "hw/virtio/dataplane/vring.h"
19
22
#include "qemu/error-report.h"
24
/* vring_map can be coupled with vring_unmap or (if you still have the
25
* value returned in *mr) memory_region_unref.
27
static void *vring_map(MemoryRegion **mr, hwaddr phys, hwaddr len,
30
MemoryRegionSection section = memory_region_find(get_system_memory(), phys, len);
32
if (!section.mr || int128_get64(section.size) < len) {
35
if (is_write && section.readonly) {
38
if (!memory_region_is_ram(section.mr)) {
42
/* Ignore regions with dirty logging, we cannot mark them dirty */
43
if (memory_region_is_logging(section.mr)) {
48
return memory_region_get_ram_ptr(section.mr) + section.offset_within_region;
51
memory_region_unref(section.mr);
56
static void vring_unmap(void *buffer, bool is_write)
61
mr = qemu_ram_addr_from_host(buffer, &addr);
62
memory_region_unref(mr);
21
65
/* Map the guest's vring to host memory */
22
66
bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
28
72
vring->broken = false;
30
hostmem_init(&vring->hostmem);
31
vring_ptr = hostmem_lookup(&vring->hostmem, vring_addr, vring_size, true);
74
vring_ptr = vring_map(&vring->mr, vring_addr, vring_size, true);
33
76
error_report("Failed to map vring "
34
77
"addr %#" HWADDR_PRIx " size %" HWADDR_PRIu,
54
97
virtio_queue_set_last_avail_idx(vdev, n, vring->last_avail_idx);
55
98
virtio_queue_invalidate_signalled_used(vdev, n);
57
hostmem_finalize(&vring->hostmem);
100
memory_region_unref(vring->mr);
60
103
/* Disable guest->host notifies */
110
153
return vring_need_event(vring_used_event(&vring->vr), new, old);
157
static int get_desc(Vring *vring, VirtQueueElement *elem,
158
struct vring_desc *desc)
165
if (desc->flags & VRING_DESC_F_WRITE) {
167
iov = &elem->in_sg[*num];
168
addr = &elem->in_addr[*num];
170
num = &elem->out_num;
171
iov = &elem->out_sg[*num];
172
addr = &elem->out_addr[*num];
174
/* If it's an output descriptor, they're all supposed
175
* to come before any input descriptors. */
176
if (unlikely(elem->in_num)) {
177
error_report("Descriptor has out after in");
182
/* Stop for now if there are not enough iovecs available. */
183
if (*num >= VIRTQUEUE_MAX_SIZE) {
187
/* TODO handle non-contiguous memory across region boundaries */
188
iov->iov_base = vring_map(&mr, desc->addr, desc->len,
189
desc->flags & VRING_DESC_F_WRITE);
190
if (!iov->iov_base) {
191
error_report("Failed to map descriptor addr %#" PRIx64 " len %u",
192
(uint64_t)desc->addr, desc->len);
196
/* The MemoryRegion is looked up again and unref'ed later, leave the
198
iov->iov_len = desc->len;
113
204
/* This is stolen from linux/drivers/vhost/vhost.c. */
114
static int get_indirect(Vring *vring,
115
struct iovec iov[], struct iovec *iov_end,
116
unsigned int *out_num, unsigned int *in_num,
205
static int get_indirect(Vring *vring, VirtQueueElement *elem,
117
206
struct vring_desc *indirect)
119
208
struct vring_desc desc;
120
209
unsigned int i = 0, count, found = 0;
122
212
/* Sanity check */
123
213
if (unlikely(indirect->len % sizeof(desc))) {
141
231
struct vring_desc *desc_ptr;
143
234
/* Translate indirect descriptor */
144
desc_ptr = hostmem_lookup(&vring->hostmem,
145
indirect->addr + found * sizeof(desc),
146
sizeof(desc), false);
235
desc_ptr = vring_map(&mr,
236
indirect->addr + found * sizeof(desc),
237
sizeof(desc), false);
148
239
error_report("Failed to map indirect descriptor "
149
240
"addr %#" PRIx64 " len %zu",
173
/* Stop for now if there are not enough iovecs available. */
174
if (iov >= iov_end) {
178
iov->iov_base = hostmem_lookup(&vring->hostmem, desc.addr, desc.len,
179
desc.flags & VRING_DESC_F_WRITE);
180
if (!iov->iov_base) {
181
error_report("Failed to map indirect descriptor"
182
"addr %#" PRIx64 " len %u",
183
(uint64_t)desc.addr, desc.len);
184
vring->broken = true;
187
iov->iov_len = desc.len;
190
/* If this is an input descriptor, increment that count. */
191
if (desc.flags & VRING_DESC_F_WRITE) {
194
/* If it's an output descriptor, they're all supposed
195
* to come before any input descriptors. */
196
if (unlikely(*in_num)) {
197
error_report("Indirect descriptor "
198
"has out after in: idx %u", i);
199
vring->broken = true;
265
ret = get_desc(vring, elem, &desc);
267
vring->broken |= (ret == -EFAULT);
205
271
} while (desc.flags & VRING_DESC_F_NEXT);
275
void vring_free_element(VirtQueueElement *elem)
279
/* This assumes that the iovecs, if changed, are never moved past
280
* the end of the valid area. This is true if iovec manipulations
281
* are done with iov_discard_front and iov_discard_back.
283
for (i = 0; i < elem->out_num; i++) {
284
vring_unmap(elem->out_sg[i].iov_base, false);
287
for (i = 0; i < elem->in_num; i++) {
288
vring_unmap(elem->in_sg[i].iov_base, true);
291
g_slice_free(VirtQueueElement, elem);
209
294
/* This looks in the virtqueue and for the first available buffer, and converts
210
295
* it to an iovec for convenient access. Since descriptors consist of some
211
296
* number of output then some number of input descriptors, it's actually two
218
303
* Stolen from linux/drivers/vhost/vhost.c.
220
305
int vring_pop(VirtIODevice *vdev, Vring *vring,
221
struct iovec iov[], struct iovec *iov_end,
222
unsigned int *out_num, unsigned int *in_num)
306
VirtQueueElement **p_elem)
224
308
struct vring_desc desc;
225
309
unsigned int i, head, found = 0, num = vring->vr.num;
226
310
uint16_t avail_idx, last_avail_idx;
311
VirtQueueElement *elem = NULL;
228
314
/* If there was a fatal error then refuse operation */
229
315
if (vring->broken) {
233
320
/* Check it isn't doing very strange things with descriptor numbers. */
238
325
if (unlikely((uint16_t)(avail_idx - last_avail_idx) > num)) {
239
326
error_report("Guest moved used index from %u to %u",
240
327
last_avail_idx, avail_idx);
241
vring->broken = true;
245
332
/* If there's nothing new since last we looked. */
246
333
if (avail_idx == last_avail_idx) {
250
338
/* Only get avail ring entries after they have been exposed by guest. */
254
342
* the index we've seen. */
255
343
head = vring->vr.avail->ring[last_avail_idx % num];
345
elem = g_slice_new(VirtQueueElement);
347
elem->in_num = elem->out_num = 0;
257
349
/* If their number is silly, that's an error. */
258
350
if (unlikely(head >= num)) {
259
351
error_report("Guest says index %u > %u is available", head, num);
260
vring->broken = true;
264
356
if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
265
357
vring_avail_event(&vring->vr) = vring->vr.avail->idx;
268
/* When we start there are none of either input nor output. */
269
*out_num = *in_num = 0;
273
362
if (unlikely(i >= num)) {
274
363
error_report("Desc index is %u > %u, head = %u", i, num, head);
275
vring->broken = true;
278
367
if (unlikely(++found > num)) {
279
368
error_report("Loop detected: last one at %u vq size %u head %u",
281
vring->broken = true;
284
373
desc = vring->vr.desc[i];
289
378
if (desc.flags & VRING_DESC_F_INDIRECT) {
290
int ret = get_indirect(vring, iov, iov_end, out_num, in_num, &desc);
379
ret = get_indirect(vring, elem, &desc);
297
/* If there are not enough iovecs left, stop for now. The caller
298
* should check if there are more descs available once they have dealt
299
* with the current set.
301
if (iov >= iov_end) {
305
/* TODO handle non-contiguous memory across region boundaries */
306
iov->iov_base = hostmem_lookup(&vring->hostmem, desc.addr, desc.len,
307
desc.flags & VRING_DESC_F_WRITE);
308
if (!iov->iov_base) {
309
error_report("Failed to map vring desc addr %#" PRIx64 " len %u",
310
(uint64_t)desc.addr, desc.len);
311
vring->broken = true;
314
iov->iov_len = desc.len;
317
if (desc.flags & VRING_DESC_F_WRITE) {
318
/* If this is an input descriptor,
319
* increment that count. */
322
/* If it's an output descriptor, they're all supposed
323
* to come before any input descriptors. */
324
if (unlikely(*in_num)) {
325
error_report("Descriptor has out after in: idx %d", i);
326
vring->broken = true;
386
ret = get_desc(vring, elem, &desc);
332
392
} while (desc.flags & VRING_DESC_F_NEXT);
334
394
/* On success, increment avail index. */
335
395
vring->last_avail_idx++;
401
if (ret == -EFAULT) {
402
vring->broken = true;
405
vring_free_element(elem);
339
411
/* After we've used one of their buffers, we tell them about it.
341
413
* Stolen from linux/drivers/vhost/vhost.c.
343
void vring_push(Vring *vring, unsigned int head, int len)
415
void vring_push(Vring *vring, VirtQueueElement *elem, int len)
345
417
struct vring_used_elem *used;
418
unsigned int head = elem->index;
421
vring_free_element(elem);
348
423
/* Don't touch vring if a fatal error occurred */
349
424
if (vring->broken) {