qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Hervé Poussineau" <hpoussin@reactos.org>
To: qemu-devel@nongnu.org
Cc: "Hervé Poussineau" <hpoussin@reactos.org>,
	"Leon Alrae" <leon.alrae@imgtec.com>,
	"Aurelien Jarno" <aurelien@aurel32.net>,
	"Paolo Bonzini" <pbonzini@redhat.com>
Subject: [Qemu-devel] [PATCH v2 02/17] dma/rc4030: create custom DMA address space
Date: Wed, 27 May 2015 14:19:45 +0200	[thread overview]
Message-ID: <1432729200-5322-3-git-send-email-hpoussin@reactos.org> (raw)
In-Reply-To: <1432729200-5322-1-git-send-email-hpoussin@reactos.org>

Add a new memory region in system address space where DMA address space
definition (the 'translation table') belongs, so we can update on the fly
the DMA address space.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
Cc: Paolo Bonzini <pbonzini@redhat.com>
 hw/dma/rc4030.c | 163 +++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 126 insertions(+), 37 deletions(-)

diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index af26632..84039dc 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -25,6 +25,7 @@
 #include "hw/hw.h"
 #include "hw/mips/mips.h"
 #include "qemu/timer.h"
+#include "exec/address-spaces.h"
 
 /********************************************************/
 /* debug rc4030 */
@@ -47,6 +48,8 @@ do { fprintf(stderr, "rc4030 ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } whi
 /********************************************************/
 /* rc4030 emulation                                     */
 
+#define MAX_TL_ENTRIES 512
+
 typedef struct dma_pagetable_entry {
     int32_t frame;
     int32_t owner;
@@ -96,6 +99,16 @@ typedef struct rc4030State
     qemu_irq timer_irq;
     qemu_irq jazz_bus_irq;
 
+    /* biggest translation table */
+    MemoryRegion dma_tt;
+    /* translation table memory region alias, added to system RAM */
+    MemoryRegion dma_tt_alias;
+    /* whole DMA memory region, root of DMA address space */
+    MemoryRegion dma_mr;
+    /* translation table entry aliases, added to DMA memory region */
+    MemoryRegion dma_mrs[MAX_TL_ENTRIES];
+    AddressSpace dma_as;
+
     MemoryRegion iomem_chipset;
     MemoryRegion iomem_jazzio;
 } rc4030State;
@@ -265,6 +278,97 @@ static uint32_t rc4030_readb(void *opaque, hwaddr addr)
     return (v >> (8 * (addr & 0x3))) & 0xff;
 }
 
+static void rc4030_dma_as_update_one(rc4030State *s, int index, uint32_t frame)
+{
+    if (index < MAX_TL_ENTRIES) {
+        memory_region_set_enabled(&s->dma_mrs[index], false);
+    }
+
+    if (!frame) {
+        return;
+    }
+
+    if (index >= MAX_TL_ENTRIES) {
+        qemu_log_mask(LOG_UNIMP,
+                      "rc4030: trying to use too high "
+                      "translation table entry %d (max allowed=%d)",
+                      index, MAX_TL_ENTRIES);
+        return;
+    }
+    memory_region_set_alias_offset(&s->dma_mrs[index], frame);
+    memory_region_set_enabled(&s->dma_mrs[index], true);
+}
+
+static void rc4030_dma_tt_write(void *opaque, hwaddr addr, uint64_t data,
+                                unsigned int size)
+{
+    rc4030State *s = opaque;
+
+    /* write memory */
+    memcpy(memory_region_get_ram_ptr(&s->dma_tt) + addr, &data, size);
+
+    /* update dma address space (only if frame field has been written) */
+    if (addr % sizeof(dma_pagetable_entry) == 0) {
+        int index = addr / sizeof(dma_pagetable_entry);
+        memory_region_transaction_begin();
+        rc4030_dma_as_update_one(s, index, (uint32_t)data);
+        memory_region_transaction_commit();
+    }
+}
+
+static const MemoryRegionOps rc4030_dma_tt_ops = {
+    .write = rc4030_dma_tt_write,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+};
+
+static void rc4030_dma_tt_update(rc4030State *s, uint32_t new_tl_base,
+                                 uint32_t new_tl_limit)
+{
+    int entries, i;
+    dma_pagetable_entry *dma_tl_contents;
+
+    if (s->dma_tl_limit) {
+        /* write old dma tl table to physical memory */
+        memory_region_del_subregion(get_system_memory(), &s->dma_tt_alias);
+        cpu_physical_memory_write(s->dma_tl_limit & 0x7fffffff,
+                                  memory_region_get_ram_ptr(&s->dma_tt),
+                                  memory_region_size(&s->dma_tt_alias));
+    }
+    object_unparent(OBJECT(&s->dma_tt_alias));
+
+    s->dma_tl_base = new_tl_base;
+    s->dma_tl_limit = new_tl_limit;
+    new_tl_base &= 0x7fffffff;
+
+    if (s->dma_tl_limit) {
+        uint64_t dma_tt_size;
+        if (s->dma_tl_limit <= memory_region_size(&s->dma_tt)) {
+            dma_tt_size = s->dma_tl_limit;
+        } else {
+            dma_tt_size = memory_region_size(&s->dma_tt);
+        }
+        memory_region_init_alias(&s->dma_tt_alias, NULL,
+                                 "dma-table-alias",
+                                 &s->dma_tt, 0, dma_tt_size);
+        dma_tl_contents = memory_region_get_ram_ptr(&s->dma_tt);
+        cpu_physical_memory_read(new_tl_base, dma_tl_contents, dma_tt_size);
+
+        memory_region_transaction_begin();
+        entries = dma_tt_size / sizeof(dma_pagetable_entry);
+        for (i = 0; i < entries; i++) {
+            rc4030_dma_as_update_one(s, i, dma_tl_contents[i].frame);
+        }
+        memory_region_add_subregion(get_system_memory(), new_tl_base,
+                                    &s->dma_tt_alias);
+        memory_region_transaction_commit();
+    } else {
+        memory_region_init(&s->dma_tt_alias, NULL,
+                           "dma-table-alias", 0);
+    }
+}
+
+
 static void rc4030_writel(void *opaque, hwaddr addr, uint32_t val)
 {
     rc4030State *s = opaque;
@@ -279,11 +383,11 @@ static void rc4030_writel(void *opaque, hwaddr addr, uint32_t val)
         break;
     /* DMA transl. table base */
     case 0x0018:
-        s->dma_tl_base = val;
+        rc4030_dma_tt_update(s, val, s->dma_tl_limit);
         break;
     /* DMA transl. table limit */
     case 0x0020:
-        s->dma_tl_limit = val;
+        rc4030_dma_tt_update(s, s->dma_tl_base, val);
         break;
     /* DMA transl. table invalidated */
     case 0x0028:
@@ -590,7 +694,7 @@ static void rc4030_reset(void *opaque)
     s->invalid_address_register = 0;
 
     memset(s->dma_regs, 0, sizeof(s->dma_regs));
-    s->dma_tl_base = s->dma_tl_limit = 0;
+    rc4030_dma_tt_update(s, 0, 0);
 
     s->remote_failed_address = s->memory_failed_address = 0;
     s->cache_maint = 0;
@@ -675,39 +779,8 @@ static void rc4030_save(QEMUFile *f, void *opaque)
 void rc4030_dma_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write)
 {
     rc4030State *s = opaque;
-    hwaddr entry_addr;
-    hwaddr phys_addr;
-    dma_pagetable_entry entry;
-    int index;
-    int ncpy, i;
-
-    i = 0;
-    for (;;) {
-        if (i == len) {
-            break;
-        }
-
-        ncpy = DMA_PAGESIZE - (addr & (DMA_PAGESIZE - 1));
-        if (ncpy > len - i)
-            ncpy = len - i;
-
-        /* Get DMA translation table entry */
-        index = addr / DMA_PAGESIZE;
-        if (index >= s->dma_tl_limit / sizeof(dma_pagetable_entry)) {
-            break;
-        }
-        entry_addr = s->dma_tl_base + index * sizeof(dma_pagetable_entry);
-        /* XXX: not sure. should we really use only lowest bits? */
-        entry_addr &= 0x7fffffff;
-        cpu_physical_memory_read(entry_addr, &entry, sizeof(entry));
-
-        /* Read/write data at right place */
-        phys_addr = entry.frame + (addr & (DMA_PAGESIZE - 1));
-        cpu_physical_memory_rw(phys_addr, &buf[i], ncpy, is_write);
-
-        i += ncpy;
-        addr += ncpy;
-    }
+    address_space_rw(&s->dma_as, addr, MEMTXATTRS_UNSPECIFIED, buf, len,
+                     is_write);
 }
 
 static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_write)
@@ -733,7 +806,8 @@ static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_wri
     dma_addr = s->dma_regs[n][DMA_REG_ADDRESS];
 
     /* Read/write data at right place */
-    rc4030_dma_memory_rw(opaque, dma_addr, buf, len, is_write);
+    address_space_rw(&s->dma_as, dma_addr, MEMTXATTRS_UNSPECIFIED,
+                     buf, len, is_write);
 
     s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_TC_INTR;
     s->dma_regs[n][DMA_REG_COUNT] -= len;
@@ -800,6 +874,7 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
                   MemoryRegion *sysmem)
 {
     rc4030State *s;
+    int i;
 
     s = g_malloc0(sizeof(rc4030State));
 
@@ -821,5 +896,19 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
                           "rc4030.jazzio", 0x00001000);
     memory_region_add_subregion(sysmem, 0xf0000000, &s->iomem_jazzio);
 
+    memory_region_init_rom_device(&s->dma_tt, NULL,
+                                  &rc4030_dma_tt_ops, s, "dma-table",
+                                  MAX_TL_ENTRIES * sizeof(dma_pagetable_entry),
+                                  NULL);
+    memory_region_init(&s->dma_tt_alias, NULL, "dma-table-alias", 0);
+    memory_region_init(&s->dma_mr, NULL, "dma", INT32_MAX);
+    for (i = 0; i < MAX_TL_ENTRIES; ++i) {
+        memory_region_init_alias(&s->dma_mrs[i], NULL, "dma-alias",
+                                 get_system_memory(), 0, DMA_PAGESIZE);
+        memory_region_set_enabled(&s->dma_mrs[i], false);
+        memory_region_add_subregion(&s->dma_mr, i * DMA_PAGESIZE,
+                                    &s->dma_mrs[i]);
+    }
+    address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
     return s;
 }
-- 
2.1.4

  parent reply	other threads:[~2015-05-27 12:23 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-27 12:19 [Qemu-devel] [PATCH v2 00/17] net/dp8393x and dma/rc4030 improvements Hervé Poussineau
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 01/17] mips jazz: compile only in 64 bit little endian Hervé Poussineau
2015-06-02 11:02   ` Aurelien Jarno
2015-06-02 18:04     ` Hervé Poussineau
2015-06-02 19:08       ` Aurelien Jarno
2015-05-27 12:19 ` Hervé Poussineau [this message]
2015-06-02 11:02   ` [Qemu-devel] [PATCH v2 02/17] dma/rc4030: create custom DMA address space Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 03/17] dma/rc4030: use AddressSpace and address_space_rw in users Hervé Poussineau
2015-06-02 11:02   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 04/17] dma/rc4030: do not use old_mmio accesses Hervé Poussineau
2015-06-02 11:03   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 05/17] dma/rc4030: document register at offset 0x210 Hervé Poussineau
2015-06-02 11:03   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 06/17] dma/rc4030: use trace events instead of custom logging Hervé Poussineau
2015-06-02 11:03   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 07/17] dma/rc4030: convert to QOM Hervé Poussineau
2015-06-02 11:03   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 08/17] net/dp8393x: always calculate proper checksums Hervé Poussineau
2015-06-02 11:03   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 09/17] net/dp8393x: do not use old_mmio accesses Hervé Poussineau
2015-06-02 11:03   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 10/17] net/dp8393x: use dp8393x_ prefix for all functions Hervé Poussineau
2015-06-02 11:04   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 11/17] net/dp8393x: QOM'ify Hervé Poussineau
2015-06-02 11:04   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 12/17] net/dp8393x: add PROM to store MAC address Hervé Poussineau
2015-06-02 11:04   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 13/17] net/dp8393x: add load/save support Hervé Poussineau
2015-06-02 11:04   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 14/17] net/dp8393x: correctly reset in_use field Hervé Poussineau
2015-06-02 11:04   ` Aurelien Jarno
2015-06-02 18:05     ` Hervé Poussineau
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 15/17] net/dp8393x: fix hardware reset Hervé Poussineau
2015-06-02 11:05   ` Aurelien Jarno
2015-05-27 12:19 ` [Qemu-devel] [PATCH v2 16/17] net/dp8393x: repair can_receive() method Hervé Poussineau
2015-06-02 11:05   ` Aurelien Jarno
2015-06-03 20:33     ` Hervé Poussineau
2015-05-27 12:20 ` [Qemu-devel] [PATCH v2 17/17] [RFC] dma/rc4030: do multiple calls to address_space_rw when doing DMA transfers Hervé Poussineau

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=1432729200-5322-3-git-send-email-hpoussin@reactos.org \
    --to=hpoussin@reactos.org \
    --cc=aurelien@aurel32.net \
    --cc=leon.alrae@imgtec.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).