Commit 576156ff authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'bonzini/iommu-for-anthony' into staging



# By Paolo Bonzini (12) and others
# Via Paolo Bonzini
* bonzini/iommu-for-anthony: (25 commits)
  memory: render_memory_region: factor out fr constant setters
  memory: as_update_topology_pass: Improve comments
  memory: Fix comment typo
  memory: give name to every AddressSpace
  dma: eliminate DMAContext
  spapr_vio: take care of creating our own AddressSpace/DMAContext
  pci: use memory core for iommu support
  dma: eliminate old-style IOMMU support
  spapr: use memory core for iommu support
  spapr: make IOMMU translation go through IOMMUTLBEntry
  spapr: convert TCE API to use an opaque type
  vfio: abort if an emulated iommu is used
  memory: Add iommu map/unmap notifiers
  memory: iommu support
  memory: make section size a 128-bit integer
  exec: reorganize mem_add to match Int128 version
  Revert "s390x: reduce TARGET_PHYS_ADDR_SPACE_BITS to 62"
  Revert "memory: limit sections in the radix tree to the actual address space size"
  exec: return MemoryRegion from address_space_translate
  exec: Implement subpage_read/write via address_space_rw
  ...

Message-id: 1371739493-10187-1-git-send-email-pbonzini@redhat.com
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parents b1588c3f 2eb74e1a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -256,8 +256,8 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
    }

    sz = size;
    section = address_space_translate(&address_space_memory, paddr, &xlat, &sz,
                                      false);
    section = address_space_translate_for_iotlb(&address_space_memory, paddr,
                                                &xlat, &sz);
    assert(sz >= TARGET_PAGE_SIZE);

#if defined(DEBUG_TLB)
+11 −179
Original line number Diff line number Diff line
@@ -14,41 +14,33 @@

/* #define DEBUG_IOMMU */

static void do_dma_memory_set(AddressSpace *as,
                              dma_addr_t addr, uint8_t c, dma_addr_t len)
int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len)
{
    dma_barrier(as, DMA_DIRECTION_FROM_DEVICE);

#define FILLBUF_SIZE 512
    uint8_t fillbuf[FILLBUF_SIZE];
    int l;
    bool error = false;

    memset(fillbuf, c, FILLBUF_SIZE);
    while (len > 0) {
        l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
        address_space_rw(as, addr, fillbuf, l, true);
        error |= address_space_rw(as, addr, fillbuf, l, true);
        len -= l;
        addr += l;
    }
}

int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len)
{
    dma_barrier(dma, DMA_DIRECTION_FROM_DEVICE);

    if (dma_has_iommu(dma)) {
        return iommu_dma_memory_set(dma, addr, c, len);
    return error;
}
    do_dma_memory_set(dma->as, addr, c, len);

    return 0;
}

void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, DMAContext *dma)
void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, AddressSpace *as)
{
    qsg->sg = g_malloc(alloc_hint * sizeof(ScatterGatherEntry));
    qsg->nsg = 0;
    qsg->nalloc = alloc_hint;
    qsg->size = 0;
    qsg->dma = dma;
    qsg->as = as;
}

void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len)
@@ -108,7 +100,7 @@ static void dma_bdrv_unmap(DMAAIOCB *dbs)
    int i;

    for (i = 0; i < dbs->iov.niov; ++i) {
        dma_memory_unmap(dbs->sg->dma, dbs->iov.iov[i].iov_base,
        dma_memory_unmap(dbs->sg->as, dbs->iov.iov[i].iov_base,
                         dbs->iov.iov[i].iov_len, dbs->dir,
                         dbs->iov.iov[i].iov_len);
    }
@@ -156,7 +148,7 @@ static void dma_bdrv_cb(void *opaque, int ret)
    while (dbs->sg_cur_index < dbs->sg->nsg) {
        cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte;
        cur_len = dbs->sg->sg[dbs->sg_cur_index].len - dbs->sg_cur_byte;
        mem = dma_memory_map(dbs->sg->dma, cur_addr, &cur_len, dbs->dir);
        mem = dma_memory_map(dbs->sg->as, cur_addr, &cur_len, dbs->dir);
        if (!mem)
            break;
        qemu_iovec_add(&dbs->iov, mem, cur_len);
@@ -253,7 +245,7 @@ static uint64_t dma_buf_rw(uint8_t *ptr, int32_t len, QEMUSGList *sg,
    while (len > 0) {
        ScatterGatherEntry entry = sg->sg[sg_cur_index++];
        int32_t xfer = MIN(len, entry.len);
        dma_memory_rw(sg->dma, entry.base, ptr, xfer, dir);
        dma_memory_rw(sg->as, entry.base, ptr, xfer, dir);
        ptr += xfer;
        len -= xfer;
        resid -= xfer;
@@ -277,163 +269,3 @@ void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
{
    bdrv_acct_start(bs, cookie, sg->size, type);
}

bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len,
                            DMADirection dir)
{
    hwaddr paddr, plen;

#ifdef DEBUG_IOMMU
    fprintf(stderr, "dma_memory_check context=%p addr=0x" DMA_ADDR_FMT
            " len=0x" DMA_ADDR_FMT " dir=%d\n", dma, addr, len, dir);
#endif

    while (len) {
        if (dma->translate(dma, addr, &paddr, &plen, dir) != 0) {
            return false;
        }

        /* The translation might be valid for larger regions. */
        if (plen > len) {
            plen = len;
        }

        if (!address_space_access_valid(dma->as, paddr, len,
                                        dir == DMA_DIRECTION_FROM_DEVICE)) {
            return false;
        }

        len -= plen;
        addr += plen;
    }

    return true;
}

int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr,
                        void *buf, dma_addr_t len, DMADirection dir)
{
    hwaddr paddr, plen;
    int err;

#ifdef DEBUG_IOMMU
    fprintf(stderr, "dma_memory_rw context=%p addr=0x" DMA_ADDR_FMT " len=0x"
            DMA_ADDR_FMT " dir=%d\n", dma, addr, len, dir);
#endif

    while (len) {
        err = dma->translate(dma, addr, &paddr, &plen, dir);
        if (err) {
	    /*
             * In case of failure on reads from the guest, we clean the
             * destination buffer so that a device that doesn't test
             * for errors will not expose qemu internal memory.
	     */
	    memset(buf, 0, len);
            return -1;
        }

        /* The translation might be valid for larger regions. */
        if (plen > len) {
            plen = len;
        }

        address_space_rw(dma->as, paddr, buf, plen, dir == DMA_DIRECTION_FROM_DEVICE);

        len -= plen;
        addr += plen;
        buf += plen;
    }

    return 0;
}

int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c,
                         dma_addr_t len)
{
    hwaddr paddr, plen;
    int err;

#ifdef DEBUG_IOMMU
    fprintf(stderr, "dma_memory_set context=%p addr=0x" DMA_ADDR_FMT
            " len=0x" DMA_ADDR_FMT "\n", dma, addr, len);
#endif

    while (len) {
        err = dma->translate(dma, addr, &paddr, &plen,
                             DMA_DIRECTION_FROM_DEVICE);
        if (err) {
            return err;
        }

        /* The translation might be valid for larger regions. */
        if (plen > len) {
            plen = len;
        }

        do_dma_memory_set(dma->as, paddr, c, plen);

        len -= plen;
        addr += plen;
    }

    return 0;
}

void dma_context_init(DMAContext *dma, AddressSpace *as, DMATranslateFunc translate,
                      DMAMapFunc map, DMAUnmapFunc unmap)
{
#ifdef DEBUG_IOMMU
    fprintf(stderr, "dma_context_init(%p, %p, %p, %p)\n",
            dma, translate, map, unmap);
#endif
    dma->as = as;
    dma->translate = translate;
    dma->map = map;
    dma->unmap = unmap;
}

void *iommu_dma_memory_map(DMAContext *dma, dma_addr_t addr, dma_addr_t *len,
                           DMADirection dir)
{
    int err;
    hwaddr paddr, plen;
    void *buf;

    if (dma->map) {
        return dma->map(dma, addr, len, dir);
    }

    plen = *len;
    err = dma->translate(dma, addr, &paddr, &plen, dir);
    if (err) {
        return NULL;
    }

    /*
     * If this is true, the virtual region is contiguous,
     * but the translated physical region isn't. We just
     * clamp *len, much like address_space_map() does.
     */
    if (plen < *len) {
        *len = plen;
    }

    buf = address_space_map(dma->as, paddr, &plen, dir == DMA_DIRECTION_FROM_DEVICE);
    *len = plen;

    return buf;
}

void iommu_dma_memory_unmap(DMAContext *dma, void *buffer, dma_addr_t len,
                            DMADirection dir, dma_addr_t access_len)
{
    if (dma->unmap) {
        dma->unmap(dma, buffer, len, dir, access_len);
        return;
    }

    address_space_unmap(dma->as, buffer, len, dir == DMA_DIRECTION_FROM_DEVICE,
                        access_len);

}
+242 −216

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, uint64_t prp1, uint64_t prp2,
        return NVME_INVALID_FIELD | NVME_DNR;
    }

    qemu_sglist_init(qsg, num_prps, pci_dma_context(&n->parent_obj));
    pci_dma_sglist_init(qsg, &n->parent_obj, num_prps);
    qemu_sglist_add(qsg, prp1, trans_len);
    len -= trans_len;
    if (len) {
+1 −1
Original line number Diff line number Diff line
@@ -726,7 +726,7 @@ int rom_load_all(void)
        addr  = rom->addr;
        addr += rom->romsize;
        section = memory_region_find(get_system_memory(), rom->addr, 1);
        rom->isrom = section.size && memory_region_is_rom(section.mr);
        rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
    }
    qemu_register_reset(rom_reset, NULL);
    roms_loaded = 1;
Loading