From patchwork Wed Jun 8 11:33:31 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 1775 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:55:46 -0000 Delivered-To: patches@linaro.org Received: by 10.52.181.10 with SMTP id ds10cs168045vdc; Wed, 8 Jun 2011 04:33:44 -0700 (PDT) Received: by 10.204.16.216 with SMTP id p24mr461908bka.5.1307532823733; Wed, 08 Jun 2011 04:33:43 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk [81.2.115.146]) by mx.google.com with ESMTPS id n8si1426541bka.53.2011.06.08.04.33.41 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 08 Jun 2011 04:33:42 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) client-ip=81.2.115.146; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) smtp.mail=pm215@archaic.org.uk Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1QUH0v-00074m-Ey; Wed, 08 Jun 2011 12:33:33 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Paul Brook , Anthony Liguori , Markus Armbruster , =?UTF-8?q?Juha=20Riihim=C3=A4ki?= Subject: [PATCH RFC 1/3] sysbus: Add support for resizing and unmapping MMIOs Date: Wed, 8 Jun 2011 12:33:31 +0100 Message-Id: <1307532813-27175-2-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1307532813-27175-1-git-send-email-peter.maydell@linaro.org> References: <1307532813-27175-1-git-send-email-peter.maydell@linaro.org> MIME-Version: 1.0 From: Juha Riihimäki Add new functions sysbus_mmio_unmap() and sysbus_mmio_resize() which allow a sysbus device user to trim the size of the device's mmio region and also to unmap it. The rationale here is twofold: * Some generic qdev devices might have an mmio region that doesn't match the specific implementation. For example usb-ohci creates an 0x1000 byte mmio for its registers, but the instantiation of the OHCI controller on OMAP3 has only an 0x400 byte space in the memory map. Using resize lets us not worry about how overlapping mapped regions are resolved. * The OMAP GPMC (general purpose memory controller) has a set of registers which allow the guest to control whether and at what size various of its subdevices are mapped. At the moment QEMU's omap_gpmc model isn't qdevified, but when it and its children are this will be necessary. Signed-off-by: Juha Riihimäki Reviewed-by: Peter Maydell --- hw/sysbus.c | 37 +++++++++++++++++++++++++++++++++++++ hw/sysbus.h | 2 ++ 2 files changed, 39 insertions(+), 0 deletions(-) diff --git a/hw/sysbus.c b/hw/sysbus.c index 2e22be7..01ebe47 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -39,6 +39,23 @@ void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) } } +void sysbus_mmio_unmap(SysBusDevice *dev, int n) +{ + assert(n >= 0 && n < dev->num_mmio); + + if (dev->mmio[n].addr == (target_phys_addr_t)-1) { + /* region already unmapped */ + return; + } + if (dev->mmio[n].cb) { + dev->mmio[n].cb(dev, (target_phys_addr_t)-1); + } else { + cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size, + IO_MEM_UNASSIGNED); + } + dev->mmio[n].addr = (target_phys_addr_t)-1; +} + void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr) { assert(n >= 0 && n < dev->num_mmio); @@ -61,6 +78,26 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr) } } +void sysbus_mmio_resize(SysBusDevice *dev, int n, target_phys_addr_t newsize) +{ + target_phys_addr_t addr; + assert(n >= 0 && n < dev->num_mmio); + + if (newsize != dev->mmio[n].size) { + addr = dev->mmio[n].addr; + if (addr != (target_phys_addr_t)-1) { + /* The expected use case is that resizes will only happen + * on unmapped regions, but we handle the already-mapped + * case by temporarily unmapping and remapping. + */ + sysbus_mmio_unmap(dev, n); + } + dev->mmio[n].size = newsize; + if (addr != (target_phys_addr_t)-1) { + sysbus_mmio_map(dev, n, addr); + } + } +} /* Request an IRQ source. The actual IRQ object may be populated later. */ void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p) diff --git a/hw/sysbus.h b/hw/sysbus.h index 4e8cb16..70e2488 100644 --- a/hw/sysbus.h +++ b/hw/sysbus.h @@ -53,6 +53,8 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size); void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq); void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr); +void sysbus_mmio_unmap(SysBusDevice *dev, int n); +void sysbus_mmio_resize(SysBusDevice *dev, int n, target_phys_addr_t newsize); /* Legacy helper function for creating devices. */ DeviceState *sysbus_create_varargs(const char *name,