From patchwork Mon May 6 14:26:16 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 241692 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id DAFE92C00EC for ; Tue, 7 May 2013 00:37:23 +1000 (EST) Received: from localhost ([::1]:43999 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UZMXa-0000h4-3G for incoming@patchwork.ozlabs.org; Mon, 06 May 2013 10:37:22 -0400 Received: from eggs.gnu.org ([208.118.235.92]:41883) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UZMNm-0006Xm-Df for qemu-devel@nongnu.org; Mon, 06 May 2013 10:27:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UZMNe-0005ok-MQ for qemu-devel@nongnu.org; Mon, 06 May 2013 10:27:14 -0400 Received: from david.siemens.de ([192.35.17.14]:16147) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UZMNe-0005oJ-60 for qemu-devel@nongnu.org; Mon, 06 May 2013 10:27:06 -0400 Received: from mail1.siemens.de (localhost [127.0.0.1]) by david.siemens.de (8.13.6/8.13.6) with ESMTP id r46EQLQM005837; Mon, 6 May 2013 16:26:21 +0200 Received: from mchn199C.mchp.siemens.de ([139.25.109.49]) by mail1.siemens.de (8.13.6/8.13.6) with ESMTP id r46EQJBS011305; Mon, 6 May 2013 16:26:21 +0200 From: Jan Kiszka To: qemu-devel Date: Mon, 6 May 2013 16:26:16 +0200 Message-Id: <06fa1813d8aa0da470fdb1ef13db504335c3218a.1367849167.git.jan.kiszka@siemens.com> 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.4.x X-Received-From: 192.35.17.14 Cc: Paolo Bonzini , Liu Ping Fan , =?UTF-8?q?Andreas=20F=C3=A4rber?= Subject: [Qemu-devel] [RFC][PATCH 13/15] ioport: Switch dispatching to memory core layer X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The current ioport dispatcher is a complex beast, mostly due to the need to deal with old portio interface users. But we can overcome it without converting all portio users by embedding the required base address of a MemoryRegionPortio access into that data structure. That removes the need to have the additional MemoryRegionIORange structure in the loop on every access. To handle old portio memory ops, we simply hook memory_region_iorange_read/write into the normal dispatch handler, calling them when standard region handler is not set, but old_portio is. We can drop the additional aliasing of ioport regions and can also the special address space listener. cpu_in/out now simply call into address_space_read/write. Signed-off-by: Jan Kiszka --- exec.c | 25 ---------- include/exec/ioport.h | 1 - include/exec/memory-internal.h | 2 - include/exec/memory.h | 3 +- ioport.c | 49 +++++++++++-------- memory.c | 101 ++++++++++++++------------------------- 6 files changed, 66 insertions(+), 115 deletions(-) diff --git a/exec.c b/exec.c index 9c582b1..992e16a 100644 --- a/exec.c +++ b/exec.c @@ -1679,24 +1679,6 @@ static void core_log_global_stop(MemoryListener *listener) cpu_physical_memory_set_dirty_tracking(0); } -static void io_region_add(MemoryListener *listener, - MemoryRegionSection *section) -{ - MemoryRegionIORange *mrio = g_new(MemoryRegionIORange, 1); - - mrio->mr = section->mr; - mrio->offset = section->offset_within_region; - iorange_init(&mrio->iorange, &memory_region_iorange_ops, - section->offset_within_address_space, section->size); - ioport_register(&mrio->iorange); -} - -static void io_region_del(MemoryListener *listener, - MemoryRegionSection *section) -{ - isa_unassign_ioport(section->offset_within_address_space, section->size); -} - static MemoryListener core_memory_listener = { .begin = core_begin, .log_global_start = core_log_global_start, @@ -1704,12 +1686,6 @@ static MemoryListener core_memory_listener = { .priority = 1, }; -static MemoryListener io_memory_listener = { - .region_add = io_region_add, - .region_del = io_region_del, - .priority = 0, -}; - static MemoryListener tcg_memory_listener = { .commit = tcg_commit, }; @@ -1752,7 +1728,6 @@ static void memory_map_init(void) address_space_io.name = "I/O"; memory_listener_register(&core_memory_listener, &address_space_memory); - memory_listener_register(&io_memory_listener, &address_space_io); memory_listener_register(&tcg_memory_listener, &address_space_memory); dma_context_init(&dma_context_memory, &address_space_memory, diff --git a/include/exec/ioport.h b/include/exec/ioport.h index eb99ffe..b476857 100644 --- a/include/exec/ioport.h +++ b/include/exec/ioport.h @@ -56,7 +56,6 @@ typedef struct PortioList { struct MemoryRegion *address_space; unsigned nr; struct MemoryRegion **regions; - struct MemoryRegion **aliases; void *opaque; const char *name; } PortioList; diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 1b156fd..3134990 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -128,8 +128,6 @@ static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start, void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, int dirty_flags); -extern const IORangeOps memory_region_iorange_ops; - #endif #endif diff --git a/include/exec/memory.h b/include/exec/memory.h index 0087555..5c9a958 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -151,6 +151,7 @@ struct MemoryRegionPortio { unsigned size; IOPortReadFunc *read; IOPortWriteFunc *write; + uint32_t base; /* private field */ }; #define PORTIO_END_OF_LIST() { } @@ -810,7 +811,7 @@ void mtree_info(fprintf_function mon_printf, void *f); * address_space_init: initializes an address space * * @as: an uninitialized #AddressSpace - * @root: a #MemoryRegion that routes addesses for the address space + * @root: a #MemoryRegion that routes addresses for the address space */ void address_space_init(AddressSpace *as, MemoryRegion *root); diff --git a/ioport.c b/ioport.c index 56470c5..9f15567 100644 --- a/ioport.c +++ b/ioport.c @@ -28,6 +28,7 @@ #include "exec/ioport.h" #include "trace.h" #include "exec/memory.h" +#include "exec/address-spaces.h" /***********************************************************/ /* IO Port */ @@ -279,27 +280,34 @@ void cpu_outb(pio_addr_t addr, uint8_t val) { LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); trace_cpu_out(addr, val); - ioport_write(0, addr, val); + address_space_write(&address_space_io, addr, &val, 1); } void cpu_outw(pio_addr_t addr, uint16_t val) { + uint8_t buf[2]; + LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); trace_cpu_out(addr, val); - ioport_write(1, addr, val); + stw_p(buf, val); + address_space_write(&address_space_io, addr, buf, 2); } void cpu_outl(pio_addr_t addr, uint32_t val) { + uint8_t buf[4]; + LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); trace_cpu_out(addr, val); - ioport_write(2, addr, val); + stl_p(buf, val); + address_space_write(&address_space_io, addr, buf, 4); } uint8_t cpu_inb(pio_addr_t addr) { uint8_t val; - val = ioport_read(0, addr); + + address_space_read(&address_space_io, addr, &val, 1); trace_cpu_in(addr, val); LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); return val; @@ -307,8 +315,11 @@ uint8_t cpu_inb(pio_addr_t addr) uint16_t cpu_inw(pio_addr_t addr) { + uint8_t buf[2]; uint16_t val; - val = ioport_read(1, addr); + + address_space_read(&address_space_io, addr, buf, 2); + val = lduw_p(buf); trace_cpu_in(addr, val); LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); return val; @@ -316,8 +327,11 @@ uint16_t cpu_inw(pio_addr_t addr) uint32_t cpu_inl(pio_addr_t addr) { + uint8_t buf[4]; uint32_t val; - val = ioport_read(2, addr); + + address_space_read(&address_space_io, addr, buf, 4); + val = ldl_p(buf); trace_cpu_in(addr, val); LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); return val; @@ -336,7 +350,6 @@ void portio_list_init(PortioList *piolist, piolist->ports = callbacks; piolist->nr = 0; piolist->regions = g_new0(MemoryRegion *, n); - piolist->aliases = g_new0(MemoryRegion *, n); piolist->address_space = NULL; piolist->opaque = opaque; piolist->name = name; @@ -345,7 +358,6 @@ void portio_list_init(PortioList *piolist, void portio_list_destroy(PortioList *piolist) { g_free(piolist->regions); - g_free(piolist->aliases); } static void portio_list_add_1(PortioList *piolist, @@ -355,7 +367,7 @@ static void portio_list_add_1(PortioList *piolist, { MemoryRegionPortio *pio; MemoryRegionOps *ops; - MemoryRegion *region, *alias; + MemoryRegion *region; unsigned i; /* Copy the sub-list and null-terminate it. */ @@ -366,25 +378,24 @@ static void portio_list_add_1(PortioList *piolist, /* Adjust the offsets to all be zero-based for the region. */ for (i = 0; i < count; ++i) { pio[i].offset -= off_low; + pio[i].base = start + off_low; } ops = g_new0(MemoryRegionOps, 1); ops->old_portio = pio; + ops->valid.unaligned = true; + ops->impl.unaligned = true; region = g_new(MemoryRegion, 1); - alias = g_new(MemoryRegion, 1); /* * Use an alias so that the callback is called with an absolute address, * rather than an offset relative to to start + off_low. */ memory_region_init_io(region, ops, piolist->opaque, piolist->name, - INT64_MAX); - memory_region_init_alias(alias, piolist->name, - region, start + off_low, off_high - off_low); + off_high - off_low); memory_region_add_subregion(piolist->address_space, - start + off_low, alias); + start + off_low, region); piolist->regions[piolist->nr] = region; - piolist->aliases[piolist->nr] = alias; ++piolist->nr; } @@ -427,19 +438,15 @@ void portio_list_add(PortioList *piolist, void portio_list_del(PortioList *piolist) { - MemoryRegion *mr, *alias; + MemoryRegion *mr; unsigned i; for (i = 0; i < piolist->nr; ++i) { mr = piolist->regions[i]; - alias = piolist->aliases[i]; - memory_region_del_subregion(piolist->address_space, alias); - memory_region_destroy(alias); + memory_region_del_subregion(piolist->address_space, mr); memory_region_destroy(mr); g_free((MemoryRegionOps *)mr->ops); g_free(mr); - g_free(alias); piolist->regions[i] = NULL; - piolist->aliases[i] = NULL; } } diff --git a/memory.c b/memory.c index fca0370..9731dd0 100644 --- a/memory.c +++ b/memory.c @@ -380,79 +380,42 @@ static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset, return NULL; } -static void memory_region_iorange_read(IORange *iorange, - uint64_t offset, - unsigned width, - uint64_t *data) -{ - MemoryRegionIORange *mrio - = container_of(iorange, MemoryRegionIORange, iorange); - MemoryRegion *mr = mrio->mr; - - offset += mrio->offset; - if (mr->ops->old_portio) { - const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset, - width, false); - - *data = ((uint64_t)1 << (width * 8)) - 1; - if (mrp) { - *data = mrp->read(mr->opaque, offset); - } else if (width == 2) { - mrp = find_portio(mr, offset - mrio->offset, 1, false); - assert(mrp); - *data = mrp->read(mr->opaque, offset) | - (mrp->read(mr->opaque, offset + 1) << 8); - } - return; +static uint64_t memory_region_iorange_read(MemoryRegion *mr, + uint64_t offset, + unsigned width) +{ + const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false); + uint64_t data; + + data = ((uint64_t)1 << (width * 8)) - 1; + if (mrp) { + data = mrp->read(mr->opaque, mrp->base + offset); + } else if (width == 2) { + mrp = find_portio(mr, offset, 1, false); + assert(mrp); + data = mrp->read(mr->opaque, mrp->base + offset) | + (mrp->read(mr->opaque, mrp->base + offset + 1) << 8); } - *data = 0; - access_with_adjusted_size(offset, data, width, - mr->ops->impl.min_access_size, - mr->ops->impl.max_access_size, - memory_region_read_accessor, mr); + return data; } -static void memory_region_iorange_write(IORange *iorange, +static void memory_region_iorange_write(MemoryRegion *mr, uint64_t offset, unsigned width, uint64_t data) { - MemoryRegionIORange *mrio - = container_of(iorange, MemoryRegionIORange, iorange); - MemoryRegion *mr = mrio->mr; - - offset += mrio->offset; - if (mr->ops->old_portio) { - const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset, - width, true); - - if (mrp) { - mrp->write(mr->opaque, offset, data); - } else if (width == 2) { - mrp = find_portio(mr, offset - mrio->offset, 1, true); - assert(mrp); - mrp->write(mr->opaque, offset, data & 0xff); - mrp->write(mr->opaque, offset + 1, data >> 8); - } - return; - } - access_with_adjusted_size(offset, &data, width, - mr->ops->impl.min_access_size, - mr->ops->impl.max_access_size, - memory_region_write_accessor, mr); -} + const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true); -static void memory_region_iorange_destructor(IORange *iorange) -{ - g_free(container_of(iorange, MemoryRegionIORange, iorange)); + if (mrp) { + mrp->write(mr->opaque, mrp->base + offset, data); + } else if (width == 2) { + mrp = find_portio(mr, offset, 1, true); + assert(mrp); + mrp->write(mr->opaque, mrp->base + offset, data & 0xff); + mrp->write(mr->opaque, mrp->base + offset + 1, data >> 8); + } } -const IORangeOps memory_region_iorange_ops = { - .read = memory_region_iorange_read, - .write = memory_region_iorange_write, - .destructor = memory_region_iorange_destructor, -}; - static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) { AddressSpace *as; @@ -854,7 +817,11 @@ static uint64_t memory_region_dispatch_read1(MemoryRegion *mr, } if (!mr->ops->read) { - return mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr); + if (mr->ops->old_portio) { + return memory_region_iorange_read(mr, addr, size); + } else { + return mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr); + } } /* FIXME: support unaligned access */ @@ -907,7 +874,11 @@ static void memory_region_dispatch_write(MemoryRegion *mr, adjust_endianness(mr, &data, size); if (!mr->ops->write) { - mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, data); + if (mr->ops->old_portio) { + memory_region_iorange_write(mr, addr, size, data); + } else { + mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, data); + } return; }