From: Aurelien Jarno <aurelien@aurel32.net>
To: "Hervé Poussineau" <hpoussin@reactos.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Leon Alrae <leon.alrae@imgtec.com>,
qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v2 02/17] dma/rc4030: create custom DMA address space
Date: Tue, 2 Jun 2015 13:02:44 +0200 [thread overview]
Message-ID: <20150602110244.GB26298@aurel32.net> (raw)
In-Reply-To: <1432729200-5322-3-git-send-email-hpoussin@reactos.org>
On 2015-05-27 14:19, Hervé Poussineau wrote:
> 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;
> }
I don't have a big knowledge of the memory API, but it clearly looks
cleaner than the current code.
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
--
Aurelien Jarno GPG: 4096R/1DDD8C9B
aurelien@aurel32.net http://www.aurel32.net
next prev parent reply other threads:[~2015-06-02 11:02 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 ` [Qemu-devel] [PATCH v2 02/17] dma/rc4030: create custom DMA address space Hervé Poussineau
2015-06-02 11:02 ` Aurelien Jarno [this message]
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=20150602110244.GB26298@aurel32.net \
--to=aurelien@aurel32.net \
--cc=hpoussin@reactos.org \
--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).