~ubuntu-branches/ubuntu/vivid/qemu/vivid

« back to all changes in this revision

Viewing changes to hw/virtio/dataplane/vring.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-02-25 22:31:43 UTC
  • mfrom: (1.8.5)
  • Revision ID: package-import@ubuntu.com-20140225223143-odhqxfc60wxrjl15
Tags: 2.0.0~rc1+dfsg-0ubuntu1
* Merge 2.0.0-rc1
* debian/rules: consolidate ppc filter entries.
* Move qemu-system-arch64 into qemu-system-arm
* debian/patches/define-trusty-machine-type.patch: define a trusty machine
  type, currently the same as pc-i440fx-2.0, to put is in a better position
  to enable live migrations from trusty onward.  (LP: #1294823)
* debian/control: build-dep on libfdt >= 1.4.0  (LP: #1295072)
* Merge latest upstream git to commit dc9528f
* Debian/rules:
  - remove -enable-uname-release=2.6.32
  - don't make the aarch64 target Ubuntu-specific.
* Remove patches which are now upstream:
  - fix-smb-security-share.patch
  - slirp-smb-redirect-port-445-too.patch 
  - linux-user-Implement-sendmmsg-syscall.patch (better version is upstream)
  - signal-added-a-wrapper-for-sigprocmask-function.patch
  - ubuntu/signal-sigsegv-protection-on-do_sigprocmask.patch
  - ubuntu/Don-t-block-SIGSEGV-at-more-places.patch
  - ubuntu/ppc-force-cpu-threads-count-to-be-power-of-2.patch
* add link for /usr/share/qemu/bios-256k.bin
* Remove all linaro patches.
* Remove all arm64/ patches.  Many but not all are upstream.
* Remove CVE-2013-4377.patch which is upstream.
* debian/control-in: don't make qemu-system-aarch64 ubuntu-specific

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 */
16
16
 
17
17
#include "trace.h"
 
18
#include "hw/hw.h"
 
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"
20
23
 
 
24
/* vring_map can be coupled with vring_unmap or (if you still have the
 
25
 * value returned in *mr) memory_region_unref.
 
26
 */
 
27
static void *vring_map(MemoryRegion **mr, hwaddr phys, hwaddr len,
 
28
                       bool is_write)
 
29
{
 
30
    MemoryRegionSection section = memory_region_find(get_system_memory(), phys, len);
 
31
 
 
32
    if (!section.mr || int128_get64(section.size) < len) {
 
33
        goto out;
 
34
    }
 
35
    if (is_write && section.readonly) {
 
36
        goto out;
 
37
    }
 
38
    if (!memory_region_is_ram(section.mr)) {
 
39
        goto out;
 
40
    }
 
41
 
 
42
    /* Ignore regions with dirty logging, we cannot mark them dirty */
 
43
    if (memory_region_is_logging(section.mr)) {
 
44
        goto out;
 
45
    }
 
46
 
 
47
    *mr = section.mr;
 
48
    return memory_region_get_ram_ptr(section.mr) + section.offset_within_region;
 
49
 
 
50
out:
 
51
    memory_region_unref(section.mr);
 
52
    *mr = NULL;
 
53
    return NULL;
 
54
}
 
55
 
 
56
static void vring_unmap(void *buffer, bool is_write)
 
57
{
 
58
    ram_addr_t addr;
 
59
    MemoryRegion *mr;
 
60
 
 
61
    mr = qemu_ram_addr_from_host(buffer, &addr);
 
62
    memory_region_unref(mr);
 
63
}
 
64
 
21
65
/* Map the guest's vring to host memory */
22
66
bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
23
67
{
27
71
 
28
72
    vring->broken = false;
29
73
 
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);
32
75
    if (!vring_ptr) {
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);
56
99
 
57
 
    hostmem_finalize(&vring->hostmem);
 
100
    memory_region_unref(vring->mr);
58
101
}
59
102
 
60
103
/* Disable guest->host notifies */
110
153
    return vring_need_event(vring_used_event(&vring->vr), new, old);
111
154
}
112
155
 
 
156
 
 
157
static int get_desc(Vring *vring, VirtQueueElement *elem,
 
158
                    struct vring_desc *desc)
 
159
{
 
160
    unsigned *num;
 
161
    struct iovec *iov;
 
162
    hwaddr *addr;
 
163
    MemoryRegion *mr;
 
164
 
 
165
    if (desc->flags & VRING_DESC_F_WRITE) {
 
166
        num = &elem->in_num;
 
167
        iov = &elem->in_sg[*num];
 
168
        addr = &elem->in_addr[*num];
 
169
    } else {
 
170
        num = &elem->out_num;
 
171
        iov = &elem->out_sg[*num];
 
172
        addr = &elem->out_addr[*num];
 
173
 
 
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");
 
178
            return -EFAULT;
 
179
        }
 
180
    }
 
181
 
 
182
    /* Stop for now if there are not enough iovecs available. */
 
183
    if (*num >= VIRTQUEUE_MAX_SIZE) {
 
184
        return -ENOBUFS;
 
185
    }
 
186
 
 
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);
 
193
        return -EFAULT;
 
194
    }
 
195
 
 
196
    /* The MemoryRegion is looked up again and unref'ed later, leave the
 
197
     * ref in place.  */
 
198
    iov->iov_len = desc->len;
 
199
    *addr = desc->addr;
 
200
    *num += 1;
 
201
    return 0;
 
202
}
 
203
 
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)
118
207
{
119
208
    struct vring_desc desc;
120
209
    unsigned int i = 0, count, found = 0;
 
210
    int ret;
121
211
 
122
212
    /* Sanity check */
123
213
    if (unlikely(indirect->len % sizeof(desc))) {
139
229
 
140
230
    do {
141
231
        struct vring_desc *desc_ptr;
 
232
        MemoryRegion *mr;
142
233
 
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);
147
238
        if (!desc_ptr) {
148
239
            error_report("Failed to map indirect descriptor "
149
240
                         "addr %#" PRIx64 " len %zu",
153
244
            return -EFAULT;
154
245
        }
155
246
        desc = *desc_ptr;
 
247
        memory_region_unref(mr);
156
248
 
157
249
        /* Ensure descriptor has been loaded before accessing fields */
158
250
        barrier(); /* read_barrier_depends(); */
170
262
            return -EFAULT;
171
263
        }
172
264
 
173
 
        /* Stop for now if there are not enough iovecs available. */
174
 
        if (iov >= iov_end) {
175
 
            return -ENOBUFS;
176
 
        }
177
 
 
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;
185
 
            return -EFAULT;
186
 
        }
187
 
        iov->iov_len = desc.len;
188
 
        iov++;
189
 
 
190
 
        /* If this is an input descriptor, increment that count. */
191
 
        if (desc.flags & VRING_DESC_F_WRITE) {
192
 
            *in_num += 1;
193
 
        } else {
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;
200
 
                return -EFAULT;
201
 
            }
202
 
            *out_num += 1;
 
265
        ret = get_desc(vring, elem, &desc);
 
266
        if (ret < 0) {
 
267
            vring->broken |= (ret == -EFAULT);
 
268
            return ret;
203
269
        }
204
270
        i = desc.next;
205
271
    } while (desc.flags & VRING_DESC_F_NEXT);
206
272
    return 0;
207
273
}
208
274
 
 
275
void vring_free_element(VirtQueueElement *elem)
 
276
{
 
277
    int i;
 
278
 
 
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.
 
282
     */
 
283
    for (i = 0; i < elem->out_num; i++) {
 
284
        vring_unmap(elem->out_sg[i].iov_base, false);
 
285
    }
 
286
 
 
287
    for (i = 0; i < elem->in_num; i++) {
 
288
        vring_unmap(elem->in_sg[i].iov_base, true);
 
289
    }
 
290
 
 
291
    g_slice_free(VirtQueueElement, elem);
 
292
}
 
293
 
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.
219
304
 */
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)
223
307
{
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;
 
312
    int ret;
227
313
 
228
314
    /* If there was a fatal error then refuse operation */
229
315
    if (vring->broken) {
230
 
        return -EFAULT;
 
316
        ret = -EFAULT;
 
317
        goto out;
231
318
    }
232
319
 
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;
242
 
        return -EFAULT;
 
328
        ret = -EFAULT;
 
329
        goto out;
243
330
    }
244
331
 
245
332
    /* If there's nothing new since last we looked. */
246
333
    if (avail_idx == last_avail_idx) {
247
 
        return -EAGAIN;
 
334
        ret = -EAGAIN;
 
335
        goto out;
248
336
    }
249
337
 
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];
256
344
 
 
345
    elem = g_slice_new(VirtQueueElement);
 
346
    elem->index = head;
 
347
    elem->in_num = elem->out_num = 0;
 
348
    
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;
261
 
        return -EFAULT;
 
352
        ret = -EFAULT;
 
353
        goto out;
262
354
    }
263
355
 
264
356
    if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
265
357
        vring_avail_event(&vring->vr) = vring->vr.avail->idx;
266
358
    }
267
359
 
268
 
    /* When we start there are none of either input nor output. */
269
 
    *out_num = *in_num = 0;
270
 
 
271
360
    i = head;
272
361
    do {
273
362
        if (unlikely(i >= num)) {
274
363
            error_report("Desc index is %u > %u, head = %u", i, num, head);
275
 
            vring->broken = true;
276
 
            return -EFAULT;
 
364
            ret = -EFAULT;
 
365
            goto out;
277
366
        }
278
367
        if (unlikely(++found > num)) {
279
368
            error_report("Loop detected: last one at %u vq size %u head %u",
280
369
                         i, num, head);
281
 
            vring->broken = true;
282
 
            return -EFAULT;
 
370
            ret = -EFAULT;
 
371
            goto out;
283
372
        }
284
373
        desc = vring->vr.desc[i];
285
374
 
287
376
        barrier();
288
377
 
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);
291
380
            if (ret < 0) {
292
 
                return ret;
 
381
                goto out;
293
382
            }
294
383
            continue;
295
384
        }
296
385
 
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.
300
 
         */
301
 
        if (iov >= iov_end) {
302
 
            return -ENOBUFS;
303
 
        }
304
 
 
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;
312
 
            return -EFAULT;
313
 
        }
314
 
        iov->iov_len  = desc.len;
315
 
        iov++;
316
 
 
317
 
        if (desc.flags & VRING_DESC_F_WRITE) {
318
 
            /* If this is an input descriptor,
319
 
             * increment that count. */
320
 
            *in_num += 1;
321
 
        } else {
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;
327
 
                return -EFAULT;
328
 
            }
329
 
            *out_num += 1;
330
 
        }
 
386
        ret = get_desc(vring, elem, &desc);
 
387
        if (ret < 0) {
 
388
            goto out;
 
389
        }
 
390
 
331
391
        i = desc.next;
332
392
    } while (desc.flags & VRING_DESC_F_NEXT);
333
393
 
334
394
    /* On success, increment avail index. */
335
395
    vring->last_avail_idx++;
 
396
    *p_elem = elem;
336
397
    return head;
 
398
 
 
399
out:
 
400
    assert(ret < 0);
 
401
    if (ret == -EFAULT) {
 
402
        vring->broken = true;
 
403
    }
 
404
    if (elem) {
 
405
        vring_free_element(elem);
 
406
    }
 
407
    *p_elem = NULL;
 
408
    return ret;
337
409
}
338
410
 
339
411
/* After we've used one of their buffers, we tell them about it.
340
412
 *
341
413
 * Stolen from linux/drivers/vhost/vhost.c.
342
414
 */
343
 
void vring_push(Vring *vring, unsigned int head, int len)
 
415
void vring_push(Vring *vring, VirtQueueElement *elem, int len)
344
416
{
345
417
    struct vring_used_elem *used;
 
418
    unsigned int head = elem->index;
346
419
    uint16_t new;
347
420
 
 
421
    vring_free_element(elem);
 
422
 
348
423
    /* Don't touch vring if a fatal error occurred */
349
424
    if (vring->broken) {
350
425
        return;