Blame 0009-fw_cfg_mem-introduce-the-data_width-property.patch

391fb8
From 5e7e3b47666b777f3bf44cd91d87130f8ca1a7c1 Mon Sep 17 00:00:00 2001
391fb8
From: Laszlo Ersek <lersek@redhat.com>
391fb8
Date: Mon, 22 Dec 2014 13:11:40 +0100
391fb8
Subject: [PATCH 09/15] fw_cfg_mem: introduce the "data_width" property
391fb8
391fb8
The "data_width" property is capable of changing the maximum valid access
391fb8
size to the MMIO data register, and resizes the memory region similarly,
391fb8
at device realization time.
391fb8
391fb8
The default value of "data_memwidth" is set so that we don't yet diverge
391fb8
from "fw_cfg_data_mem_ops".
391fb8
391fb8
Most of the fw_cfg_mem users will stick with the default, and for them we
391fb8
should continue using the statically allocated "fw_cfg_data_mem_ops". This
391fb8
is beneficial for debugging because gdb can resolve pointers referencing
391fb8
static objects to the names of those objects.
391fb8
391fb8
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
391fb8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
391fb8
Message-id: 1419250305-31062-7-git-send-email-pbonzini@redhat.com
391fb8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
391fb8
(cherry picked from commit cfaadf0e89e7c2a47462d5f96390c9a9b4de037c)
391fb8
---
391fb8
 hw/nvram/fw_cfg.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++----
391fb8
 1 file changed, 74 insertions(+), 5 deletions(-)
391fb8
391fb8
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
391fb8
index 910ae14..2950d68 100644
391fb8
--- a/hw/nvram/fw_cfg.c
391fb8
+++ b/hw/nvram/fw_cfg.c
391fb8
@@ -77,6 +77,8 @@ struct FWCfgMemState {
391fb8
     /*< public >*/
391fb8
 
391fb8
     MemoryRegion ctl_iomem, data_iomem;
391fb8
+    uint32_t data_width;
391fb8
+    MemoryRegionOps wide_data_ops;
391fb8
 };
391fb8
 
391fb8
 #define JPG_FILE 0
391fb8
@@ -284,13 +286,58 @@ static uint8_t fw_cfg_read(FWCfgState *s)
391fb8
 static uint64_t fw_cfg_data_mem_read(void *opaque, hwaddr addr,
391fb8
                                      unsigned size)
391fb8
 {
391fb8
-    return fw_cfg_read(opaque);
391fb8
+    FWCfgState *s = opaque;
391fb8
+    uint8_t buf[8];
391fb8
+    unsigned i;
391fb8
+
391fb8
+    for (i = 0; i < size; ++i) {
391fb8
+        buf[i] = fw_cfg_read(s);
391fb8
+    }
391fb8
+    switch (size) {
391fb8
+    case 1:
391fb8
+        return buf[0];
391fb8
+    case 2:
391fb8
+        return lduw_he_p(buf);
391fb8
+    case 4:
391fb8
+        return (uint32_t)ldl_he_p(buf);
391fb8
+    case 8:
391fb8
+        return ldq_he_p(buf);
391fb8
+    }
391fb8
+    abort();
391fb8
 }
391fb8
 
391fb8
 static void fw_cfg_data_mem_write(void *opaque, hwaddr addr,
391fb8
                                   uint64_t value, unsigned size)
391fb8
 {
391fb8
-    fw_cfg_write(opaque, (uint8_t)value);
391fb8
+    FWCfgState *s = opaque;
391fb8
+    uint8_t buf[8];
391fb8
+    unsigned i;
391fb8
+
391fb8
+    switch (size) {
391fb8
+    case 1:
391fb8
+        buf[0] = value;
391fb8
+        break;
391fb8
+    case 2:
391fb8
+        stw_he_p(buf, value);
391fb8
+        break;
391fb8
+    case 4:
391fb8
+        stl_he_p(buf, value);
391fb8
+        break;
391fb8
+    case 8:
391fb8
+        stq_he_p(buf, value);
391fb8
+        break;
391fb8
+    default:
391fb8
+        abort();
391fb8
+    }
391fb8
+    for (i = 0; i < size; ++i) {
391fb8
+        fw_cfg_write(s, buf[i]);
391fb8
+    }
391fb8
+}
391fb8
+
391fb8
+static bool fw_cfg_data_mem_valid(void *opaque, hwaddr addr,
391fb8
+                                  unsigned size, bool is_write)
391fb8
+{
391fb8
+    return addr == 0;
391fb8
 }
391fb8
 
391fb8
 static void fw_cfg_ctl_mem_write(void *opaque, hwaddr addr,
391fb8
@@ -343,6 +390,7 @@ static const MemoryRegionOps fw_cfg_data_mem_ops = {
391fb8
     .valid = {
391fb8
         .min_access_size = 1,
391fb8
         .max_access_size = 1,
391fb8
+        .accepts = fw_cfg_data_mem_valid,
391fb8
     },
391fb8
 };
391fb8
 
391fb8
@@ -621,6 +669,9 @@ FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr)
391fb8
     SysBusDevice *sbd;
391fb8
 
391fb8
     dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
391fb8
+    qdev_prop_set_uint32(dev, "data_width",
391fb8
+                         fw_cfg_data_mem_ops.valid.max_access_size);
391fb8
+
391fb8
     fw_cfg_init1(dev);
391fb8
 
391fb8
     sbd = SYS_BUS_DEVICE(dev);
391fb8
@@ -683,18 +734,35 @@ static const TypeInfo fw_cfg_io_info = {
391fb8
 };
391fb8
 
391fb8
 
391fb8
+static Property fw_cfg_mem_properties[] = {
391fb8
+    DEFINE_PROP_UINT32("data_width", FWCfgMemState, data_width, -1),
391fb8
+    DEFINE_PROP_END_OF_LIST(),
391fb8
+};
391fb8
+
391fb8
 static void fw_cfg_mem_realize(DeviceState *dev, Error **errp)
391fb8
 {
391fb8
     FWCfgMemState *s = FW_CFG_MEM(dev);
391fb8
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
391fb8
+    const MemoryRegionOps *data_ops = &fw_cfg_data_mem_ops;
391fb8
 
391fb8
     memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops,
391fb8
                           FW_CFG(s), "fwcfg.ctl", FW_CFG_SIZE);
391fb8
     sysbus_init_mmio(sbd, &s->ctl_iomem);
391fb8
 
391fb8
-    memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops,
391fb8
-                          FW_CFG(s), "fwcfg.data",
391fb8
-                          fw_cfg_data_mem_ops.valid.max_access_size);
391fb8
+    if (s->data_width > data_ops->valid.max_access_size) {
391fb8
+        /* memberwise copy because the "old_mmio" member is const */
391fb8
+        s->wide_data_ops.read       = data_ops->read;
391fb8
+        s->wide_data_ops.write      = data_ops->write;
391fb8
+        s->wide_data_ops.endianness = data_ops->endianness;
391fb8
+        s->wide_data_ops.valid      = data_ops->valid;
391fb8
+        s->wide_data_ops.impl       = data_ops->impl;
391fb8
+
391fb8
+        s->wide_data_ops.valid.max_access_size = s->data_width;
391fb8
+        s->wide_data_ops.impl.max_access_size  = s->data_width;
391fb8
+        data_ops = &s->wide_data_ops;
391fb8
+    }
391fb8
+    memory_region_init_io(&s->data_iomem, OBJECT(s), data_ops, FW_CFG(s),
391fb8
+                          "fwcfg.data", data_ops->valid.max_access_size);
391fb8
     sysbus_init_mmio(sbd, &s->data_iomem);
391fb8
 }
391fb8
 
391fb8
@@ -703,6 +771,7 @@ static void fw_cfg_mem_class_init(ObjectClass *klass, void *data)
391fb8
     DeviceClass *dc = DEVICE_CLASS(klass);
391fb8
 
391fb8
     dc->realize = fw_cfg_mem_realize;
391fb8
+    dc->props = fw_cfg_mem_properties;
391fb8
 }
391fb8
 
391fb8
 static const TypeInfo fw_cfg_mem_info = {
391fb8
-- 
391fb8
2.1.0
391fb8