From patchwork Sat Jan 29 17:40:25 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: 80944 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 1A0F1B7109 for ; Sun, 30 Jan 2011 04:48:58 +1100 (EST) Received: from localhost ([127.0.0.1]:43040 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PjEuT-0000LI-EM for incoming@patchwork.ozlabs.org; Sat, 29 Jan 2011 12:48:29 -0500 Received: from [140.186.70.92] (port=59894 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PjEnD-00054J-HN for qemu-devel@nongnu.org; Sat, 29 Jan 2011 12:41:00 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PjEnB-0004eV-Si for qemu-devel@nongnu.org; Sat, 29 Jan 2011 12:40:59 -0500 Received: from mail-fx0-f45.google.com ([209.85.161.45]:35571) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PjEnB-0004be-Mh for qemu-devel@nongnu.org; Sat, 29 Jan 2011 12:40:57 -0500 Received: by mail-fx0-f45.google.com with SMTP id 12so4523658fxm.4 for ; Sat, 29 Jan 2011 09:40:57 -0800 (PST) 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:in-reply-to:references; bh=p5q7yLNEMpxlMNrirTWZAEJB9Cit5u+L1xzYxv+jd0o=; b=XJPSNrj53EOvYY3htQGA6JAQtbP3Q7m8Sz0OIcmZTrpnpmjhpNmUeu3quEl1YotIg2 NezEATe0rXahdcm2is3qHRDVytHm3igSBWbFdLXTvbkChFtMOwKiZejkFmtF6VD2x4du Va53VXEriDLjcIh1EPNBdELxEOcu64npRjLks= 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=NyAkNnufXMwDJxBC14JraqBu/2PYwU06uZpZH4auP+ynrRRgzKeKnqTlndPZ5TI4Fr HgkqJOJPhJIwpDFfiiGijDxk2zcqhad6EqoXht2++5QzCcT0K+pbWEC11IN8Dw3m+YUf In+yVO6eNVNpIFM0t8wAi5O0XbqDoG881D/Rg= Received: by 10.223.87.80 with SMTP id v16mr3872528fal.128.1296322857253; Sat, 29 Jan 2011 09:40:57 -0800 (PST) Received: from localhost.localdomain ([188.25.244.101]) by mx.google.com with ESMTPS id 21sm6822801fav.17.2011.01.29.09.40.55 (version=SSLv3 cipher=RC4-MD5); Sat, 29 Jan 2011 09:40:56 -0800 (PST) From: Eduard - Gabriel Munteanu To: joro@8bytes.org Date: Sat, 29 Jan 2011 19:40:25 +0200 Message-Id: <515151da731a7dddf422535979050c973cd8c95b.1296321798.git.eduard.munteanu@linux360.ro> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 209.85.161.45 Cc: kvm@vger.kernel.org, qemu-devel@nongnu.org, blauwirbel@gmail.com, yamahata@valinux.co.jp, paul@codesourcery.com, Eduard - Gabriel Munteanu , avi@redhat.com Subject: [Qemu-devel] [PATCH 04/13] ide: use the DMA memory access interface for PCI IDE controllers X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 968fdce..aea06a9 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -993,7 +993,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 697c3b4..3d3d5db 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -468,6 +468,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 c1b4caa..654ae7c 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -79,7 +79,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; @@ -141,7 +141,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 510b2de..e3432c4 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -64,7 +64,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) { @@ -72,7 +73,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); @@ -114,7 +115,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); @@ -129,11 +130,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; @@ -444,6 +445,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 = {