From patchwork Mon Mar 5 15:51:17 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avi Kivity X-Patchwork-Id: 144703 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 28252B6FA7 for ; Tue, 6 Mar 2012 02:52:13 +1100 (EST) Received: from localhost ([::1]:42512 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4aCc-0003qW-88 for incoming@patchwork.ozlabs.org; Mon, 05 Mar 2012 10:51:58 -0500 Received: from eggs.gnu.org ([208.118.235.92]:54256) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4aCL-0003i0-HD for qemu-devel@nongnu.org; Mon, 05 Mar 2012 10:51:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S4aCE-0000Yt-Of for qemu-devel@nongnu.org; Mon, 05 Mar 2012 10:51:41 -0500 Received: from mx1.redhat.com ([209.132.183.28]:1652) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4aCE-0000YQ-Gt for qemu-devel@nongnu.org; Mon, 05 Mar 2012 10:51:34 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q25FpVed009843 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 5 Mar 2012 10:51:31 -0500 Received: from cleopatra.tlv.redhat.com (cleopatra.tlv.redhat.com [10.35.255.11]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q25FpUFj005882; Mon, 5 Mar 2012 10:51:30 -0500 Received: from s01.tlv.redhat.com (s01.tlv.redhat.com [10.35.255.8]) by cleopatra.tlv.redhat.com (Postfix) with ESMTP id 39948250BAC; Mon, 5 Mar 2012 17:51:25 +0200 (IST) From: Avi Kivity To: qemu-devel@nongnu.org Date: Mon, 5 Mar 2012 17:51:17 +0200 Message-Id: <1330962677-14837-3-git-send-email-avi@redhat.com> In-Reply-To: <1330962677-14837-1-git-send-email-avi@redhat.com> References: <1330962677-14837-1-git-send-email-avi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: Mark Cave-Ayland , Alexander Graf Subject: [Qemu-devel] [PATCH 2/2] memory: fix I/O port aliases 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 Commit e58ac72b6a0 ("ioport: change portio_list not to use memory_region_set_offset()") started using aliases of I/O memory regions. Since the IORange used for the I/O was contained in the target region, the alias information (specifically, the offset into the region) was lost. This broke -vga std. Fix by allocating an independent object to hold the IORange and also the new offset. Note that I/O memory regions were conceptually broken wrt aliases in a different way: an alias can cause the same region to appear twice in an address space, but we had just one IORange to service it. This patch fixes that problem as well, since we can now have multiple IORange/MemoryRegion associations. Signed-off-by: Avi Kivity --- exec.c | 8 ++++++-- memory.c | 26 ++++++++++++++++++++------ memory.h | 9 ++++++++- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/exec.c b/exec.c index 3ce3539..1e5bbd6 100644 --- a/exec.c +++ b/exec.c @@ -3668,9 +3668,13 @@ static void io_commit(MemoryListener *listener) static void io_region_add(MemoryListener *listener, MemoryRegionSection *section) { - iorange_init(§ion->mr->iorange, &memory_region_iorange_ops, + 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(§ion->mr->iorange); + ioport_register(&mrio->iorange); } static void io_region_del(MemoryListener *listener, diff --git a/memory.c b/memory.c index 6565e2e..4c3dc49 100644 --- a/memory.c +++ b/memory.c @@ -382,16 +382,20 @@ static void memory_region_iorange_read(IORange *iorange, unsigned width, uint64_t *data) { - MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange); + 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, width, false); + 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, 1, false); + mrp = find_portio(mr, offset - mrio->offset, 1, false); assert(mrp); *data = mrp->read(mr->opaque, offset) | (mrp->read(mr->opaque, offset + 1) << 8); @@ -410,15 +414,19 @@ static void memory_region_iorange_write(IORange *iorange, unsigned width, uint64_t data) { - MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange); + 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, width, true); + 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, 1, false); + mrp = find_portio(mr, offset - mrio->offset, 1, false); assert(mrp); mrp->write(mr->opaque, offset, data & 0xff); mrp->write(mr->opaque, offset + 1, data >> 8); @@ -431,9 +439,15 @@ static void memory_region_iorange_write(IORange *iorange, memory_region_write_accessor, mr); } +static void memory_region_iorange_destructor(IORange *iorange) +{ + g_free(container_of(iorange, MemoryRegionIORange, iorange)); +} + const IORangeOps memory_region_iorange_ops = { .read = memory_region_iorange_read, .write = memory_region_iorange_write, + .destructor = memory_region_iorange_destructor, }; static AddressSpace address_space_io; diff --git a/memory.h b/memory.h index b7bccd1..53ff62b 100644 --- a/memory.h +++ b/memory.h @@ -43,6 +43,14 @@ struct MemoryRegionMmio { CPUWriteMemoryFunc *write[3]; }; +/* Internal use; thunks between old-style IORange and MemoryRegions. */ +typedef struct MemoryRegionIORange MemoryRegionIORange; +struct MemoryRegionIORange { + IORange iorange; + MemoryRegion *mr; + target_phys_addr_t offset; +}; + /* * Memory region callbacks */ @@ -117,7 +125,6 @@ struct MemoryRegion { target_phys_addr_t addr; void (*destructor)(MemoryRegion *mr); ram_addr_t ram_addr; - IORange iorange; bool subpage; bool terminates; bool readable;