From patchwork Wed Jun 1 01:38:26 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduard - Gabriel Munteanu X-Patchwork-Id: 834412 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p511d4bd024277 for ; Wed, 1 Jun 2011 01:39:05 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758584Ab1FABi7 (ORCPT ); Tue, 31 May 2011 21:38:59 -0400 Received: from mail-bw0-f46.google.com ([209.85.214.46]:39474 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933048Ab1FABi6 (ORCPT ); Tue, 31 May 2011 21:38:58 -0400 Received: by mail-bw0-f46.google.com with SMTP id 15so4139763bwz.19 for ; Tue, 31 May 2011 18:38:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:sender:from:to:cc:subject:date:message-id :x-mailer:in-reply-to:references; bh=nRehg0NbiS+RNSL2Tw3+EA66LC2oIMYDChKAEtjp+Gs=; b=MJAQPKuFUN0GmBaEOEFzI80RprCHXpd/XTCGhAc5c9q6ehO5FpoEHsntI6BflCDKCb vw0C9bzcMMm7l8z8Wx/NHU6khxHD5TWoG1Z9bMUKq6j1bvevoEMPv8XeJCGQwnLugfg8 5TQuVFW5wPlqzHDaHwSHuE1z4Vws+fmuyNV+A= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; b=jIlZrMCwcyAI8Q+sT+/IqejegksSVisBI2RwhbTauSMze1oUaPtdmhhpBBHLoVtoJM 794xYcuTjXTx3+50vojiXsnNJoiVeD9hdLDxIKBPU1ZovQ20M1xfikdwJKonH268rxXu eiBXBx4EnXuy5c1TvRFGN3dl8uu5QOUccv9RU= Received: by 10.204.126.38 with SMTP id a38mr5910059bks.195.1306892337641; Tue, 31 May 2011 18:38:57 -0700 (PDT) Received: from localhost.localdomain ([188.25.93.127]) by mx.google.com with ESMTPS id ag6sm453451bkc.18.2011.05.31.18.38.55 (version=SSLv3 cipher=OTHER); Tue, 31 May 2011 18:38:56 -0700 (PDT) From: Eduard - Gabriel Munteanu To: mst@redhat.com Cc: seabios@seabios.org, kevin@koconnor.net, joro@8bytes.org, blauwirbel@gmail.com, paul@codesourcery.com, avi@redhat.com, anthony@codemonkey.ws, av1474@comtv.ru, yamahata@valinux.co.jp, kvm@vger.kernel.org, qemu-devel@nongnu.org, benh@kernel.crashing.org, aik@ozlabs.ru, agraf@suse.de, aliguori@us.ibm.com, dwg@au1.ibm.com, rth@twiddle.net, david@gibson.dropbear.id.au, Eduard - Gabriel Munteanu Subject: [RFC PATCH 04/13] ide: use the DMA memory access interface for PCI IDE controllers Date: Wed, 1 Jun 2011 04:38:26 +0300 Message-Id: <1306892315-7306-5-git-send-email-eduard.munteanu@linux360.ro> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1306892315-7306-1-git-send-email-eduard.munteanu@linux360.ro> References: <1306892315-7306-1-git-send-email-eduard.munteanu@linux360.ro> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 01 Jun 2011 01:39:05 +0000 (UTC) Emulated PCI IDE controllers now use the memory access interface. This also allows an emulated IOMMU to translate and check accesses. Map invalidation results in cancelling DMA transfers. Since the guest OS can't properly recover the DMA results in case the mapping is changed, this is a fairly good approximation. Note this doesn't handle AHCI emulation yet! Signed-off-by: Eduard - Gabriel Munteanu --- dma-helpers.c | 23 ++++++++++++++++++----- dma.h | 4 +++- hw/ide/ahci.c | 3 ++- hw/ide/internal.h | 1 + hw/ide/macio.c | 4 ++-- hw/ide/pci.c | 18 +++++++++++------- 6 files changed, 37 insertions(+), 16 deletions(-) diff --git a/dma-helpers.c b/dma-helpers.c index 712ed89..29a74a4 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -10,12 +10,13 @@ #include "dma.h" #include "block_int.h" -void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint) +void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, DMADevice *dma) { qsg->sg = qemu_malloc(alloc_hint * sizeof(ScatterGatherEntry)); qsg->nsg = 0; qsg->nalloc = alloc_hint; qsg->size = 0; + qsg->dma = dma; } void qemu_sglist_add(QEMUSGList *qsg, target_phys_addr_t base, @@ -73,12 +74,23 @@ static void dma_bdrv_unmap(DMAAIOCB *dbs) int i; for (i = 0; i < dbs->iov.niov; ++i) { - cpu_physical_memory_unmap(dbs->iov.iov[i].iov_base, - dbs->iov.iov[i].iov_len, !dbs->is_write, - dbs->iov.iov[i].iov_len); + dma_memory_unmap(dbs->sg->dma, + dbs->iov.iov[i].iov_base, + dbs->iov.iov[i].iov_len, !dbs->is_write, + dbs->iov.iov[i].iov_len); } } +static void dma_bdrv_cancel(void *opaque) +{ + DMAAIOCB *dbs = opaque; + + bdrv_aio_cancel(dbs->acb); + dma_bdrv_unmap(dbs); + qemu_iovec_destroy(&dbs->iov); + qemu_aio_release(dbs); +} + static void dma_bdrv_cb(void *opaque, int ret) { DMAAIOCB *dbs = (DMAAIOCB *)opaque; @@ -100,7 +112,8 @@ 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 = cpu_physical_memory_map(cur_addr, &cur_len, !dbs->is_write); + mem = dma_memory_map(dbs->sg->dma, dma_bdrv_cancel, dbs, + cur_addr, &cur_len, !dbs->is_write); if (!mem) break; qemu_iovec_add(&dbs->iov, mem, cur_len); diff --git a/dma.h b/dma.h index f3bb275..2417b32 100644 --- a/dma.h +++ b/dma.h @@ -14,6 +14,7 @@ //#include "cpu.h" #include "hw/hw.h" #include "block.h" +#include "hw/dma_rw.h" typedef struct { target_phys_addr_t base; @@ -25,9 +26,10 @@ typedef struct { int nsg; int nalloc; target_phys_addr_t size; + DMADevice *dma; } QEMUSGList; -void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint); +void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, DMADevice *dma); void qemu_sglist_add(QEMUSGList *qsg, target_phys_addr_t base, target_phys_addr_t len); void qemu_sglist_destroy(QEMUSGList *qsg); diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index c6e0c77..68b87d2 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -680,7 +680,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist) if (sglist_alloc_hint > 0) { AHCI_SG *tbl = (AHCI_SG *)prdt; - qemu_sglist_init(sglist, sglist_alloc_hint); + /* FIXME: pass a proper DMADevice. */ + qemu_sglist_init(sglist, sglist_alloc_hint, NULL); for (i = 0; i < sglist_alloc_hint; i++) { /* flags_size is zero-based */ qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr), diff --git a/hw/ide/internal.h b/hw/ide/internal.h index aa198b6..b830d67 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -474,6 +474,7 @@ struct IDEDMA { struct iovec iov; QEMUIOVector qiov; BlockDriverAIOCB *aiocb; + DMADevice *dev; }; struct IDEBus { diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 7107f6b..a111481 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -78,7 +78,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) s->io_buffer_size = io->len; - qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1); + qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1, NULL); qemu_sglist_add(&s->sg, io->addr, io->len); io->addr += io->len; io->len = 0; @@ -140,7 +140,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) s->io_buffer_index = 0; s->io_buffer_size = io->len; - qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1); + qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1, NULL); qemu_sglist_add(&s->sg, io->addr, io->len); io->addr += io->len; io->len = 0; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 65cb56c..a14f2ae 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -63,7 +63,8 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write) } prd; int l, len; - qemu_sglist_init(&s->sg, s->nsector / (BMDMA_PAGE_SIZE / 512) + 1); + qemu_sglist_init(&s->sg, + s->nsector / (BMDMA_PAGE_SIZE / 512) + 1, dma->dev); s->io_buffer_size = 0; for(;;) { if (bm->cur_prd_len == 0) { @@ -71,7 +72,7 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write) if (bm->cur_prd_last || (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE) return s->io_buffer_size != 0; - cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + dma_memory_read(dma->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); @@ -113,7 +114,7 @@ static int bmdma_rw_buf(IDEDMA *dma, int is_write) if (bm->cur_prd_last || (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE) return 0; - cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + dma_memory_read(dma->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); @@ -128,11 +129,11 @@ static int bmdma_rw_buf(IDEDMA *dma, int is_write) 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); + dma_memory_write(dma->dev, 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); + dma_memory_read(dma->dev, bm->cur_prd_addr, + s->io_buffer + s->io_buffer_index, l); } bm->cur_prd_addr += l; bm->cur_prd_len -= l; @@ -436,6 +437,9 @@ void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table) continue; ide_create_drive(d->bus+bus[i], unit[i], hd_table[i]); } + + d->bmdma[0].dma.dev = &dev->dma; + d->bmdma[1].dma.dev = &dev->dma; } static const struct IDEDMAOps bmdma_ops = {