All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
To: jsnow@redhat.com, agraf@suse.de, qemu-devel@nongnu.org,
	qemu-ppc@nongnu.org
Subject: [Qemu-devel] [PATCH 2/4] macio: switch pmac_dma_write() over to new offset/len implementation
Date: Sun, 31 May 2015 21:05:30 +0100	[thread overview]
Message-ID: <1433102732-24034-3-git-send-email-mark.cave-ayland@ilande.co.uk> (raw)
In-Reply-To: <1433102732-24034-1-git-send-email-mark.cave-ayland@ilande.co.uk>

In particular, this fixes a bug whereby chains of overlapping head/tail chains
would incorrectly write over each other's remainder cache. This is the access
pattern used by OS X/Darwin and fixes an issue with a corrupt Darwin
installation in my local tests.

While we are here, rename the DBDMA_io struct property remainder to
head_remainder for clarification.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
---
 hw/ide/macio.c             |  116 ++++++++++++++++++++------------------------
 include/hw/ppc/mac_dbdma.h |    3 +-
 2 files changed, 55 insertions(+), 64 deletions(-)

diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index f1ac001..92f35e2 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -86,7 +86,7 @@ static void pmac_dma_read(BlockBackend *blk,
         MACIO_DPRINTF("--- DMA unaligned head: sector %ld, "
                       "discarding %ld bytes\n", sector_num, head_bytes);
 
-        qemu_iovec_add(&io->iov, &io->remainder, head_bytes);
+        qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes);
 
         bytes += offset & (align - 1);
         offset = offset & ~(align - 1);
@@ -100,7 +100,7 @@ static void pmac_dma_read(BlockBackend *blk,
         MACIO_DPRINTF("--- DMA unaligned tail: sector %ld, "
                       "discarding bytes %ld\n", sector_num, tail_bytes);
 
-        qemu_iovec_add(&io->iov, &io->remainder, align - tail_bytes);
+        qemu_iovec_add(&io->iov, &io->tail_remainder, align - tail_bytes);
         bytes = ROUND_UP(bytes, align);
     }
 
@@ -117,7 +117,7 @@ static void pmac_dma_read(BlockBackend *blk,
 }
 
 static void pmac_dma_write(BlockBackend *blk,
-                         int64_t sector_num, int nb_sectors,
+                         int64_t offset, int bytes,
                          void (*cb)(void *opaque, int ret), void *opaque)
 {
     DBDMA_io *io = opaque;
@@ -125,90 +125,80 @@ static void pmac_dma_write(BlockBackend *blk,
     IDEState *s = idebus_active_if(&m->bus);
     dma_addr_t dma_addr, dma_len;
     void *mem;
-    int nsector, remainder;
-    int extra = 0;
+    int64_t sector_num;
+    int nsector;
+    uint64_t align = BDRV_SECTOR_SIZE;
+    size_t head_bytes, tail_bytes;
+    bool unaligned_head = false, unaligned_tail = false;
 
     qemu_iovec_destroy(&io->iov);
     qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1);
 
-    if (io->remainder_len > 0) {
-        /* Return remainder of request */
-        int transfer = MIN(io->remainder_len, io->len);
+    sector_num = (offset >> 9);
+    nsector = (io->len >> 9);
 
-        MACIO_DPRINTF("--- processing write remainder %x\n", transfer);
-        cpu_physical_memory_read(io->addr,
-                                 &io->remainder + (0x200 - transfer),
-                                 transfer);
+    MACIO_DPRINTF("--- DMA write transfer (0x%" HWADDR_PRIx ",0x%x): "
+                  "sector_num: %ld, nsector: %d\n", io->addr, io->len,
+                  sector_num, nsector);
 
-        io->remainder_len -= transfer;
-        io->len -= transfer;
-        io->addr += transfer;
+    dma_addr = io->addr;
+    dma_len = io->len;
+    mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
+                         DMA_DIRECTION_TO_DEVICE);
 
-        s->io_buffer_index += transfer;
-        s->io_buffer_size -= transfer;
+    if (offset & (align - 1)) {
+        head_bytes = offset & (align - 1);
+        sector_num = ((offset & ~(align - 1)) >> 9);
 
-        if (io->remainder_len != 0) {
-            /* Still waiting for remainder */
-            return;
-        }
+        MACIO_DPRINTF("--- DMA unaligned head: pre-reading head sector %ld\n",
+                      sector_num);
 
-        MACIO_DPRINTF("--> prepending bounce buffer with size 0x200\n");
+        blk_pread(s->blk, (sector_num << 9), &io->head_remainder, align);
 
-        /* Sector transfer complete - prepend to request */
-        qemu_iovec_add(&io->iov, &io->remainder, 0x200);
-        extra = 1;
-    }
+        qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes);
+        qemu_iovec_add(&io->iov, mem, io->len);
 
-    if (s->drive_kind == IDE_CD) {
-        sector_num = (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9);
-    } else {
-        sector_num = ide_get_sector(s) + (s->io_buffer_index >> 9);
+        bytes += offset & (align - 1);
+        offset = offset & ~(align - 1);
+
+        unaligned_head = true;
     }
 
-    nsector = (io->len >> 9);
-    remainder = io->len - (nsector << 9);
+    if ((offset + bytes) & (align - 1)) {
+        tail_bytes = (offset + bytes) & (align - 1);
+        sector_num = (((offset + bytes) & ~(align - 1)) >> 9);
 
-    MACIO_DPRINTF("--- DMA write transfer - addr: %" HWADDR_PRIx " len: %x\n",
-                  io->addr, io->len);
-    MACIO_DPRINTF("xxx remainder: %x\n", remainder);
-    MACIO_DPRINTF("xxx sector_num: %"PRIx64"   nsector: %x\n",
-                  sector_num, nsector);
+        MACIO_DPRINTF("--- DMA unaligned tail: pre-reading tail sector %ld\n",
+                      sector_num);
 
-    dma_addr = io->addr;
-    dma_len = io->len;
-    mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
-                         DMA_DIRECTION_TO_DEVICE);
+        blk_pread(s->blk, (sector_num << 9), &io->tail_remainder, align);
 
-    if (!remainder) {
-        MACIO_DPRINTF("--- DMA write aligned - addr: %" HWADDR_PRIx
-                      " len: %x\n", io->addr, io->len);
-        qemu_iovec_add(&io->iov, mem, io->len);
-    } else {
-        /* Write up to last complete sector */
-        MACIO_DPRINTF("--- DMA write unaligned - addr: %" HWADDR_PRIx
-                      " len: %x\n", io->addr, (nsector << 9));
-        qemu_iovec_add(&io->iov, mem, (nsector << 9));
+        if (!unaligned_head) {
+            qemu_iovec_add(&io->iov, mem, io->len);
+        }
 
-        MACIO_DPRINTF("--- DMA write read    - bounce addr: %p "
-                      "remainder_len: %x\n", &io->remainder, remainder);
-        cpu_physical_memory_read(io->addr + (nsector << 9), &io->remainder,
-                                 remainder);
+        qemu_iovec_add(&io->iov, &io->tail_remainder + tail_bytes,
+                       align - tail_bytes);
+
+        bytes = ROUND_UP(bytes, align);
 
-        io->remainder_len = 0x200 - remainder;
+        unaligned_tail = true;
+    }
 
-        MACIO_DPRINTF("xxx remainder_len: %x\n", io->remainder_len);
+    if (!unaligned_head && !unaligned_tail) {
+        qemu_iovec_add(&io->iov, mem, io->len);
     }
 
-    s->io_buffer_size -= ((nsector + extra) << 9);
-    s->io_buffer_index += ((nsector + extra) << 9);
+    s->io_buffer_size -= io->len;
+    s->io_buffer_index += io->len;
 
     io->len = 0;
 
-    MACIO_DPRINTF("--- Block write transfer   - sector_num: %"PRIx64"  "
-                  "nsector: %x\n", sector_num, nsector + extra);
+    MACIO_DPRINTF("--- Block write transfer - sector_num: %" PRIx64 "  "
+                  "nsector: %x\n", (offset >> 9), (bytes >> 9));
 
-    m->aiocb = blk_aio_writev(blk, sector_num, &io->iov, nsector + extra, cb,
-                              io);
+    m->aiocb = blk_aio_writev(blk, (offset >> 9), &io->iov, (bytes >> 9),
+                              cb, io);
 }
 
 static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
@@ -340,7 +330,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
         pmac_dma_read(s->blk, offset, io->len, pmac_ide_transfer_cb, io);
         break;
     case IDE_DMA_WRITE:
-        pmac_dma_write(s->blk, sector_num, nsector, pmac_ide_transfer_cb, io);
+        pmac_dma_write(s->blk, offset, io->len, pmac_ide_transfer_cb, io);
         break;
     case IDE_DMA_TRIM:
         MACIO_DPRINTF("TRIM command issued!");
diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h
index c580327..7f247fa 100644
--- a/include/hw/ppc/mac_dbdma.h
+++ b/include/hw/ppc/mac_dbdma.h
@@ -40,7 +40,8 @@ struct DBDMA_io {
     /* DMA is in progress, don't start another one */
     bool processing;
     /* unaligned last sector of a request */
-    uint8_t remainder[0x200];
+    uint8_t head_remainder[0x200];
+    uint8_t tail_remainder[0x200];
     int remainder_len;
     QEMUIOVector iov;
 };
-- 
1.7.10.4

  parent reply	other threads:[~2015-05-31 20:06 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-31 20:05 [Qemu-devel] [PATCH 0/4] macio: change DMA methods over to offset/len implementation Mark Cave-Ayland
2015-05-31 20:05 ` [Qemu-devel] [PATCH 1/4] macio: switch pmac_dma_read() over to new " Mark Cave-Ayland
2015-06-02 20:02   ` John Snow
2015-05-31 20:05 ` Mark Cave-Ayland [this message]
2015-05-31 20:05 ` [Qemu-devel] [PATCH 3/4] macio: update comment/constants to reflect the new code Mark Cave-Ayland
2015-05-31 20:05 ` [Qemu-devel] [PATCH 4/4] macio: remove remainder_len DBDMA_io property Mark Cave-Ayland
2015-06-01 23:09 ` [Qemu-devel] [PATCH 0/4] macio: change DMA methods over to offset/len implementation John Snow
2015-06-01 23:18   ` Mark Cave-Ayland
2015-06-01 23:25     ` John Snow
2015-06-02  7:28     ` Laurent Vivier
2015-06-02 20:03 ` John Snow

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1433102732-24034-3-git-send-email-mark.cave-ayland@ilande.co.uk \
    --to=mark.cave-ayland@ilande.co.uk \
    --cc=agraf@suse.de \
    --cc=jsnow@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.