Memory accesses must go through the IOMMU layer. Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu@xxxxxxxxxxx> --- hw/ide/core.c | 46 +++++++++++++++++++++++++++++++--------------- 1 files changed, 31 insertions(+), 15 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 0b3b7c2..7f8f7df 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -26,6 +26,7 @@ #include <hw/pc.h> #include <hw/pci.h> #include <hw/scsi.h> +#include <hw/iommu.h> #include "qemu-timer.h" #include "sysemu.h" #include "dma.h" @@ -433,7 +434,12 @@ static int dma_buf_prepare(BMDMAState *bm, int is_write) uint32_t addr; uint32_t size; } prd; - int l, len; + int l, len, err, io_len; + struct iommu *iommu; + DeviceState *dev; + target_phys_addr_t io_addr; + + iommu = iommu_get(s->bus->qbus.parent, &dev); qemu_sglist_init(&s->sg, s->nsector / (IDE_PAGE_SIZE / 512) + 1); s->io_buffer_size = 0; @@ -443,7 +449,7 @@ static int dma_buf_prepare(BMDMAState *bm, int is_write) if (bm->cur_prd_last || (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE) return s->io_buffer_size != 0; - cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + err = iommu_read(iommu, dev, bm->cur_addr, (uint8_t *)&prd, 8); bm->cur_addr += 8; prd.addr = le32_to_cpu(prd.addr); prd.size = le32_to_cpu(prd.size); @@ -455,11 +461,22 @@ static int dma_buf_prepare(BMDMAState *bm, int is_write) bm->cur_prd_last = (prd.size & 0x80000000); } l = bm->cur_prd_len; - if (l > 0) { - qemu_sglist_add(&s->sg, bm->cur_prd_addr, l); - bm->cur_prd_addr += l; - bm->cur_prd_len -= l; - s->io_buffer_size += l; + while (l > 0) { + /* + * In case translation / access checking fails no + * transfer happens but we pretend it went through. + */ + err = iommu_translate(iommu, dev, bm->cur_prd_addr, + &io_addr, &io_len, !is_write); + if (!err) { + if (io_len > l) + io_len = l; + qemu_sglist_add(&s->sg, io_addr, io_len); + } + bm->cur_prd_addr += io_len; + bm->cur_prd_len -= io_len; + s->io_buffer_size += io_len; + l -= io_len; } } return 1; @@ -516,6 +533,10 @@ static int dma_buf_rw(BMDMAState *bm, int is_write) uint32_t size; } prd; int l, len; + struct iommu *iommu; + DeviceState *dev; + + iommu = iommu_get(s->bus->qbus.parent, &dev); for(;;) { l = s->io_buffer_size - s->io_buffer_index; @@ -526,7 +547,7 @@ static int dma_buf_rw(BMDMAState *bm, int is_write) if (bm->cur_prd_last || (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE) return 0; - cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + iommu_read(iommu, dev, bm->cur_addr, (uint8_t *)&prd, 8); bm->cur_addr += 8; prd.addr = le32_to_cpu(prd.addr); prd.size = le32_to_cpu(prd.size); @@ -540,13 +561,8 @@ static int dma_buf_rw(BMDMAState *bm, int is_write) if (l > bm->cur_prd_len) l = bm->cur_prd_len; if (l > 0) { - if (is_write) { - cpu_physical_memory_write(bm->cur_prd_addr, - s->io_buffer + s->io_buffer_index, l); - } else { - cpu_physical_memory_read(bm->cur_prd_addr, - s->io_buffer + s->io_buffer_index, l); - } + iommu_rw(iommu, dev, bm->cur_prd_addr, + s->io_buffer + s->io_buffer_index, l, is_write); bm->cur_prd_addr += l; bm->cur_prd_len -= l; s->io_buffer_index += l; -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html