~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to dma-helpers.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-10-22 22:47:07 UTC
  • mfrom: (1.8.3) (10.1.42 sid)
  • Revision ID: package-import@ubuntu.com-20131022224707-1lya34fw3k3f24tv
Tags: 1.6.0+dfsg-2ubuntu1
* Merge 1.6.0~rc0+dfsg-2exp from debian experimental.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
      - drop openbios-ppc and openhackware Depends to Suggests (for now)
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - New linaro patches from qemu-linaro rebasing branch
  - Dropped patches:
    * xen-simplify-xen_enabled.patch
    * sparc-linux-user-fix-missing-symbols-in-.rel-.rela.plt-sections.patch
    * main_loop-do-not-set-nonblocking-if-xen_enabled.patch
    * xen_machine_pv-do-not-create-a-dummy-CPU-in-machine-.patch
    * virtio-rng-fix-crash
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * linaro arm patches from qemu-linaro rebasing branch
  - New patches:
    * fix-pci-add: change CONFIG variable in ifdef to make sure that
      pci_add is defined.
* Add linaro patches
* Add experimental mach-virt patches for arm virtualization.
* qemu-system-common.install: add debian/tmp/usr/lib to install the
  qemu-bridge-helper

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 
15
15
/* #define DEBUG_IOMMU */
16
16
 
17
 
static void do_dma_memory_set(AddressSpace *as,
18
 
                              dma_addr_t addr, uint8_t c, dma_addr_t len)
 
17
int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len)
19
18
{
 
19
    dma_barrier(as, DMA_DIRECTION_FROM_DEVICE);
 
20
 
20
21
#define FILLBUF_SIZE 512
21
22
    uint8_t fillbuf[FILLBUF_SIZE];
22
23
    int l;
 
24
    bool error = false;
23
25
 
24
26
    memset(fillbuf, c, FILLBUF_SIZE);
25
27
    while (len > 0) {
26
28
        l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
27
 
        address_space_rw(as, addr, fillbuf, l, true);
 
29
        error |= address_space_rw(as, addr, fillbuf, l, true);
28
30
        len -= l;
29
31
        addr += l;
30
32
    }
31
 
}
32
 
 
33
 
int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len)
34
 
{
35
 
    dma_barrier(dma, DMA_DIRECTION_FROM_DEVICE);
36
 
 
37
 
    if (dma_has_iommu(dma)) {
38
 
        return iommu_dma_memory_set(dma, addr, c, len);
39
 
    }
40
 
    do_dma_memory_set(dma->as, addr, c, len);
41
 
 
42
 
    return 0;
43
 
}
44
 
 
45
 
void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, DMAContext *dma)
 
33
 
 
34
    return error;
 
35
}
 
36
 
 
37
void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint,
 
38
                      AddressSpace *as)
46
39
{
47
40
    qsg->sg = g_malloc(alloc_hint * sizeof(ScatterGatherEntry));
48
41
    qsg->nsg = 0;
49
42
    qsg->nalloc = alloc_hint;
50
43
    qsg->size = 0;
51
 
    qsg->dma = dma;
 
44
    qsg->as = as;
 
45
    qsg->dev = dev;
 
46
    object_ref(OBJECT(dev));
52
47
}
53
48
 
54
49
void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len)
65
60
 
66
61
void qemu_sglist_destroy(QEMUSGList *qsg)
67
62
{
 
63
    object_unref(OBJECT(qsg->dev));
68
64
    g_free(qsg->sg);
69
65
    memset(qsg, 0, sizeof(*qsg));
70
66
}
108
104
    int i;
109
105
 
110
106
    for (i = 0; i < dbs->iov.niov; ++i) {
111
 
        dma_memory_unmap(dbs->sg->dma, dbs->iov.iov[i].iov_base,
 
107
        dma_memory_unmap(dbs->sg->as, dbs->iov.iov[i].iov_base,
112
108
                         dbs->iov.iov[i].iov_len, dbs->dir,
113
109
                         dbs->iov.iov[i].iov_len);
114
110
    }
156
152
    while (dbs->sg_cur_index < dbs->sg->nsg) {
157
153
        cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte;
158
154
        cur_len = dbs->sg->sg[dbs->sg_cur_index].len - dbs->sg_cur_byte;
159
 
        mem = dma_memory_map(dbs->sg->dma, cur_addr, &cur_len, dbs->dir);
 
155
        mem = dma_memory_map(dbs->sg->as, cur_addr, &cur_len, dbs->dir);
160
156
        if (!mem)
161
157
            break;
162
158
        qemu_iovec_add(&dbs->iov, mem, cur_len);
253
249
    while (len > 0) {
254
250
        ScatterGatherEntry entry = sg->sg[sg_cur_index++];
255
251
        int32_t xfer = MIN(len, entry.len);
256
 
        dma_memory_rw(sg->dma, entry.base, ptr, xfer, dir);
 
252
        dma_memory_rw(sg->as, entry.base, ptr, xfer, dir);
257
253
        ptr += xfer;
258
254
        len -= xfer;
259
255
        resid -= xfer;
277
273
{
278
274
    bdrv_acct_start(bs, cookie, sg->size, type);
279
275
}
280
 
 
281
 
bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len,
282
 
                            DMADirection dir)
283
 
{
284
 
    hwaddr paddr, plen;
285
 
 
286
 
#ifdef DEBUG_IOMMU
287
 
    fprintf(stderr, "dma_memory_check context=%p addr=0x" DMA_ADDR_FMT
288
 
            " len=0x" DMA_ADDR_FMT " dir=%d\n", dma, addr, len, dir);
289
 
#endif
290
 
 
291
 
    while (len) {
292
 
        if (dma->translate(dma, addr, &paddr, &plen, dir) != 0) {
293
 
            return false;
294
 
        }
295
 
 
296
 
        /* The translation might be valid for larger regions. */
297
 
        if (plen > len) {
298
 
            plen = len;
299
 
        }
300
 
 
301
 
        len -= plen;
302
 
        addr += plen;
303
 
    }
304
 
 
305
 
    return true;
306
 
}
307
 
 
308
 
int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr,
309
 
                        void *buf, dma_addr_t len, DMADirection dir)
310
 
{
311
 
    hwaddr paddr, plen;
312
 
    int err;
313
 
 
314
 
#ifdef DEBUG_IOMMU
315
 
    fprintf(stderr, "dma_memory_rw context=%p addr=0x" DMA_ADDR_FMT " len=0x"
316
 
            DMA_ADDR_FMT " dir=%d\n", dma, addr, len, dir);
317
 
#endif
318
 
 
319
 
    while (len) {
320
 
        err = dma->translate(dma, addr, &paddr, &plen, dir);
321
 
        if (err) {
322
 
            /*
323
 
             * In case of failure on reads from the guest, we clean the
324
 
             * destination buffer so that a device that doesn't test
325
 
             * for errors will not expose qemu internal memory.
326
 
             */
327
 
            memset(buf, 0, len);
328
 
            return -1;
329
 
        }
330
 
 
331
 
        /* The translation might be valid for larger regions. */
332
 
        if (plen > len) {
333
 
            plen = len;
334
 
        }
335
 
 
336
 
        address_space_rw(dma->as, paddr, buf, plen, dir == DMA_DIRECTION_FROM_DEVICE);
337
 
 
338
 
        len -= plen;
339
 
        addr += plen;
340
 
        buf += plen;
341
 
    }
342
 
 
343
 
    return 0;
344
 
}
345
 
 
346
 
int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c,
347
 
                         dma_addr_t len)
348
 
{
349
 
    hwaddr paddr, plen;
350
 
    int err;
351
 
 
352
 
#ifdef DEBUG_IOMMU
353
 
    fprintf(stderr, "dma_memory_set context=%p addr=0x" DMA_ADDR_FMT
354
 
            " len=0x" DMA_ADDR_FMT "\n", dma, addr, len);
355
 
#endif
356
 
 
357
 
    while (len) {
358
 
        err = dma->translate(dma, addr, &paddr, &plen,
359
 
                             DMA_DIRECTION_FROM_DEVICE);
360
 
        if (err) {
361
 
            return err;
362
 
        }
363
 
 
364
 
        /* The translation might be valid for larger regions. */
365
 
        if (plen > len) {
366
 
            plen = len;
367
 
        }
368
 
 
369
 
        do_dma_memory_set(dma->as, paddr, c, plen);
370
 
 
371
 
        len -= plen;
372
 
        addr += plen;
373
 
    }
374
 
 
375
 
    return 0;
376
 
}
377
 
 
378
 
void dma_context_init(DMAContext *dma, AddressSpace *as, DMATranslateFunc translate,
379
 
                      DMAMapFunc map, DMAUnmapFunc unmap)
380
 
{
381
 
#ifdef DEBUG_IOMMU
382
 
    fprintf(stderr, "dma_context_init(%p, %p, %p, %p)\n",
383
 
            dma, translate, map, unmap);
384
 
#endif
385
 
    dma->as = as;
386
 
    dma->translate = translate;
387
 
    dma->map = map;
388
 
    dma->unmap = unmap;
389
 
}
390
 
 
391
 
void *iommu_dma_memory_map(DMAContext *dma, dma_addr_t addr, dma_addr_t *len,
392
 
                           DMADirection dir)
393
 
{
394
 
    int err;
395
 
    hwaddr paddr, plen;
396
 
    void *buf;
397
 
 
398
 
    if (dma->map) {
399
 
        return dma->map(dma, addr, len, dir);
400
 
    }
401
 
 
402
 
    plen = *len;
403
 
    err = dma->translate(dma, addr, &paddr, &plen, dir);
404
 
    if (err) {
405
 
        return NULL;
406
 
    }
407
 
 
408
 
    /*
409
 
     * If this is true, the virtual region is contiguous,
410
 
     * but the translated physical region isn't. We just
411
 
     * clamp *len, much like address_space_map() does.
412
 
     */
413
 
    if (plen < *len) {
414
 
        *len = plen;
415
 
    }
416
 
 
417
 
    buf = address_space_map(dma->as, paddr, &plen, dir == DMA_DIRECTION_FROM_DEVICE);
418
 
    *len = plen;
419
 
 
420
 
    return buf;
421
 
}
422
 
 
423
 
void iommu_dma_memory_unmap(DMAContext *dma, void *buffer, dma_addr_t len,
424
 
                            DMADirection dir, dma_addr_t access_len)
425
 
{
426
 
    if (dma->unmap) {
427
 
        dma->unmap(dma, buffer, len, dir, access_len);
428
 
        return;
429
 
    }
430
 
 
431
 
    address_space_unmap(dma->as, buffer, len, dir == DMA_DIRECTION_FROM_DEVICE,
432
 
                        access_len);
433
 
 
434
 
}