From patchwork Tue Dec 23 13:54:22 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 423715 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2D8481400D5 for ; Wed, 24 Dec 2014 01:01:29 +1100 (AEDT) Received: from localhost ([::1]:44728 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y3Q1f-0008JB-DM for incoming@patchwork.ozlabs.org; Tue, 23 Dec 2014 09:01:27 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:32996) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y3Pv2-0003lK-3l for qemu-devel@nongnu.org; Tue, 23 Dec 2014 08:54:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y3Pv0-000165-LX for qemu-devel@nongnu.org; Tue, 23 Dec 2014 08:54:35 -0500 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:54615) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y3Pv0-00015a-By for qemu-devel@nongnu.org; Tue, 23 Dec 2014 08:54:34 -0500 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1Y3Puu-00044a-Re for qemu-devel@nongnu.org; Tue, 23 Dec 2014 13:54:28 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Tue, 23 Dec 2014 13:54:22 +0000 Message-Id: <1419342867-15527-27-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1419342867-15527-1-git-send-email-peter.maydell@linaro.org> References: <1419342867-15527-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:8b0:1d0::1 Subject: [Qemu-devel] [PULL 26/31] fw_cfg_mem: introduce the "data_width" property 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 From: Laszlo Ersek The "data_width" property is capable of changing the maximum valid access size to the MMIO data register, and resizes the memory region similarly, at device realization time. The default value of "data_memwidth" is set so that we don't yet diverge from "fw_cfg_data_mem_ops". Most of the fw_cfg_mem users will stick with the default, and for them we should continue using the statically allocated "fw_cfg_data_mem_ops". This is beneficial for debugging because gdb can resolve pointers referencing static objects to the names of those objects. Signed-off-by: Laszlo Ersek Signed-off-by: Paolo Bonzini Message-id: 1419250305-31062-7-git-send-email-pbonzini@redhat.com Signed-off-by: Peter Maydell --- hw/nvram/fw_cfg.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 910ae14..2950d68 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -77,6 +77,8 @@ struct FWCfgMemState { /*< public >*/ MemoryRegion ctl_iomem, data_iomem; + uint32_t data_width; + MemoryRegionOps wide_data_ops; }; #define JPG_FILE 0 @@ -284,13 +286,58 @@ static uint8_t fw_cfg_read(FWCfgState *s) static uint64_t fw_cfg_data_mem_read(void *opaque, hwaddr addr, unsigned size) { - return fw_cfg_read(opaque); + FWCfgState *s = opaque; + uint8_t buf[8]; + unsigned i; + + for (i = 0; i < size; ++i) { + buf[i] = fw_cfg_read(s); + } + switch (size) { + case 1: + return buf[0]; + case 2: + return lduw_he_p(buf); + case 4: + return (uint32_t)ldl_he_p(buf); + case 8: + return ldq_he_p(buf); + } + abort(); } static void fw_cfg_data_mem_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - fw_cfg_write(opaque, (uint8_t)value); + FWCfgState *s = opaque; + uint8_t buf[8]; + unsigned i; + + switch (size) { + case 1: + buf[0] = value; + break; + case 2: + stw_he_p(buf, value); + break; + case 4: + stl_he_p(buf, value); + break; + case 8: + stq_he_p(buf, value); + break; + default: + abort(); + } + for (i = 0; i < size; ++i) { + fw_cfg_write(s, buf[i]); + } +} + +static bool fw_cfg_data_mem_valid(void *opaque, hwaddr addr, + unsigned size, bool is_write) +{ + return addr == 0; } static void fw_cfg_ctl_mem_write(void *opaque, hwaddr addr, @@ -343,6 +390,7 @@ static const MemoryRegionOps fw_cfg_data_mem_ops = { .valid = { .min_access_size = 1, .max_access_size = 1, + .accepts = fw_cfg_data_mem_valid, }, }; @@ -621,6 +669,9 @@ FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr) SysBusDevice *sbd; dev = qdev_create(NULL, TYPE_FW_CFG_MEM); + qdev_prop_set_uint32(dev, "data_width", + fw_cfg_data_mem_ops.valid.max_access_size); + fw_cfg_init1(dev); sbd = SYS_BUS_DEVICE(dev); @@ -683,18 +734,35 @@ static const TypeInfo fw_cfg_io_info = { }; +static Property fw_cfg_mem_properties[] = { + DEFINE_PROP_UINT32("data_width", FWCfgMemState, data_width, -1), + DEFINE_PROP_END_OF_LIST(), +}; + static void fw_cfg_mem_realize(DeviceState *dev, Error **errp) { FWCfgMemState *s = FW_CFG_MEM(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + const MemoryRegionOps *data_ops = &fw_cfg_data_mem_ops; memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops, FW_CFG(s), "fwcfg.ctl", FW_CFG_SIZE); sysbus_init_mmio(sbd, &s->ctl_iomem); - memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops, - FW_CFG(s), "fwcfg.data", - fw_cfg_data_mem_ops.valid.max_access_size); + if (s->data_width > data_ops->valid.max_access_size) { + /* memberwise copy because the "old_mmio" member is const */ + s->wide_data_ops.read = data_ops->read; + s->wide_data_ops.write = data_ops->write; + s->wide_data_ops.endianness = data_ops->endianness; + s->wide_data_ops.valid = data_ops->valid; + s->wide_data_ops.impl = data_ops->impl; + + s->wide_data_ops.valid.max_access_size = s->data_width; + s->wide_data_ops.impl.max_access_size = s->data_width; + data_ops = &s->wide_data_ops; + } + memory_region_init_io(&s->data_iomem, OBJECT(s), data_ops, FW_CFG(s), + "fwcfg.data", data_ops->valid.max_access_size); sysbus_init_mmio(sbd, &s->data_iomem); } @@ -703,6 +771,7 @@ static void fw_cfg_mem_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = fw_cfg_mem_realize; + dc->props = fw_cfg_mem_properties; } static const TypeInfo fw_cfg_mem_info = {