Blame 0004-fw_cfg-hard-separation-between-the-MMIO-and-I-O-port.patch

391fb8
From e91399538669c6480ace3eb0f63b1c99645924bc Mon Sep 17 00:00:00 2001
391fb8
From: Laszlo Ersek <lersek@redhat.com>
391fb8
Date: Mon, 22 Dec 2014 13:11:35 +0100
391fb8
Subject: [PATCH 04/15] fw_cfg: hard separation between the MMIO and I/O port
391fb8
 mappings
391fb8
391fb8
We are going to introduce a wide data register for fw_cfg, but only for
391fb8
the MMIO mapped device. The wide data register will also require the
391fb8
tightening of endiannesses.
391fb8
391fb8
However we don't want to touch the I/O port mapped fw_cfg device at all.
391fb8
391fb8
Currently QEMU provides a single fw_cfg device type that can handle both
391fb8
I/O port and MMIO mapping. This flexibility is not actually exploited by
391fb8
any board in the tree, but it renders restricting the above changes to
391fb8
MMIO very hard.
391fb8
391fb8
Therefore, let's derive two classes from TYPE_FW_CFG: TYPE_FW_CFG_IO and
391fb8
TYPE_FW_CFG_MEM.
391fb8
391fb8
TYPE_FW_CFG_IO incorporates the base I/O port and the related combined
391fb8
MemoryRegion. (NB: all boards in the tree that use the I/O port mapped
391fb8
flavor opt for the combined mapping; that is, when the data port overlays
391fb8
the high address byte of the selector port. Therefore we can drop the
391fb8
capability to map those I/O ports separately.)
391fb8
391fb8
TYPE_FW_CFG_MEM incorporates the base addresses for the MMIO selector and
391fb8
data registers, and their respective MemoryRegions.
391fb8
391fb8
The "realize" and "props" class members are specific to each new derived
391fb8
class, and become unused for the base class. The base class retains the
391fb8
"reset" member and the "vmsd" member, because the reset functionality and
391fb8
the set of migrated data are not specific to the mapping.
391fb8
391fb8
The new functions fw_cfg_init_io() and fw_cfg_init_mem() expose the
391fb8
possible mappings in separation. For now fw_cfg_init() is retained as a
391fb8
compatibility shim that enforces the above assumptions.
391fb8
391fb8
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
391fb8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
391fb8
Message-id: 1419250305-31062-2-git-send-email-pbonzini@redhat.com
391fb8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
391fb8
(cherry picked from commit 5712db6ae5101db645f71edc393368cd59bfd314)
391fb8
---
391fb8
 hw/nvram/fw_cfg.c         | 181 +++++++++++++++++++++++++++++++---------------
391fb8
 include/hw/nvram/fw_cfg.h |   2 +
391fb8
 include/qemu/typedefs.h   |   2 +
391fb8
 3 files changed, 128 insertions(+), 57 deletions(-)
391fb8
391fb8
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
391fb8
index c4b78ed..ab7bfff 100644
391fb8
--- a/hw/nvram/fw_cfg.c
391fb8
+++ b/hw/nvram/fw_cfg.c
391fb8
@@ -32,10 +32,16 @@
391fb8
 
391fb8
 #define FW_CFG_SIZE 2
391fb8
 #define FW_CFG_DATA_SIZE 1
391fb8
-#define TYPE_FW_CFG "fw_cfg"
391fb8
 #define FW_CFG_NAME "fw_cfg"
391fb8
 #define FW_CFG_PATH "/machine/" FW_CFG_NAME
391fb8
-#define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG)
391fb8
+
391fb8
+#define TYPE_FW_CFG     "fw_cfg"
391fb8
+#define TYPE_FW_CFG_IO  "fw_cfg_io"
391fb8
+#define TYPE_FW_CFG_MEM "fw_cfg_mem"
391fb8
+
391fb8
+#define FW_CFG(obj)     OBJECT_CHECK(FWCfgState,    (obj), TYPE_FW_CFG)
391fb8
+#define FW_CFG_IO(obj)  OBJECT_CHECK(FWCfgIoState,  (obj), TYPE_FW_CFG_IO)
391fb8
+#define FW_CFG_MEM(obj) OBJECT_CHECK(FWCfgMemState, (obj), TYPE_FW_CFG_MEM)
391fb8
 
391fb8
 typedef struct FWCfgEntry {
391fb8
     uint32_t len;
391fb8
@@ -50,8 +56,6 @@ struct FWCfgState {
391fb8
     SysBusDevice parent_obj;
391fb8
     /*< public >*/
391fb8
 
391fb8
-    MemoryRegion ctl_iomem, data_iomem, comb_iomem;
391fb8
-    uint32_t ctl_iobase, data_iobase;
391fb8
     FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
391fb8
     FWCfgFiles *files;
391fb8
     uint16_t cur_entry;
391fb8
@@ -59,6 +63,23 @@ struct FWCfgState {
391fb8
     Notifier machine_ready;
391fb8
 };
391fb8
 
391fb8
+struct FWCfgIoState {
391fb8
+    /*< private >*/
391fb8
+    FWCfgState parent_obj;
391fb8
+    /*< public >*/
391fb8
+
391fb8
+    MemoryRegion comb_iomem;
391fb8
+    uint32_t iobase;
391fb8
+};
391fb8
+
391fb8
+struct FWCfgMemState {
391fb8
+    /*< private >*/
391fb8
+    FWCfgState parent_obj;
391fb8
+    /*< public >*/
391fb8
+
391fb8
+    MemoryRegion ctl_iomem, data_iomem;
391fb8
+};
391fb8
+
391fb8
 #define JPG_FILE 0
391fb8
 #define BMP_FILE 1
391fb8
 
391fb8
@@ -560,19 +581,11 @@ static void fw_cfg_machine_ready(struct Notifier *n, void *data)
391fb8
     qemu_register_reset(fw_cfg_machine_reset, s);
391fb8
 }
391fb8
 
391fb8
-FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
391fb8
-                        hwaddr ctl_addr, hwaddr data_addr)
391fb8
+
391fb8
+
391fb8
+static void fw_cfg_init1(DeviceState *dev)
391fb8
 {
391fb8
-    DeviceState *dev;
391fb8
-    SysBusDevice *d;
391fb8
-    FWCfgState *s;
391fb8
-
391fb8
-    dev = qdev_create(NULL, TYPE_FW_CFG);
391fb8
-    qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port);
391fb8
-    qdev_prop_set_uint32(dev, "data_iobase", data_port);
391fb8
-    d = SYS_BUS_DEVICE(dev);
391fb8
-
391fb8
-    s = FW_CFG(dev);
391fb8
+    FWCfgState *s = FW_CFG(dev);
391fb8
 
391fb8
     assert(!object_resolve_path(FW_CFG_PATH, NULL));
391fb8
 
391fb8
@@ -580,12 +593,6 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
391fb8
 
391fb8
     qdev_init_nofail(dev);
391fb8
 
391fb8
-    if (ctl_addr) {
391fb8
-        sysbus_mmio_map(d, 0, ctl_addr);
391fb8
-    }
391fb8
-    if (data_addr) {
391fb8
-        sysbus_mmio_map(d, 1, data_addr);
391fb8
-    }
391fb8
     fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (char *)"QEMU", 4);
391fb8
     fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);
391fb8
     fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC));
391fb8
@@ -596,48 +603,48 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
391fb8
 
391fb8
     s->machine_ready.notify = fw_cfg_machine_ready;
391fb8
     qemu_add_machine_init_done_notifier(&s->machine_ready);
391fb8
+}
391fb8
+
391fb8
+FWCfgState *fw_cfg_init_io(uint32_t iobase)
391fb8
+{
391fb8
+    DeviceState *dev;
391fb8
 
391fb8
-    return s;
391fb8
+    dev = qdev_create(NULL, TYPE_FW_CFG_IO);
391fb8
+    qdev_prop_set_uint32(dev, "iobase", iobase);
391fb8
+    fw_cfg_init1(dev);
391fb8
+
391fb8
+    return FW_CFG(dev);
391fb8
 }
391fb8
 
391fb8
-static void fw_cfg_initfn(Object *obj)
391fb8
+FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr)
391fb8
 {
391fb8
-    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
391fb8
-    FWCfgState *s = FW_CFG(obj);
391fb8
-
391fb8
-    memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops, s,
391fb8
-                          "fwcfg.ctl", FW_CFG_SIZE);
391fb8
-    sysbus_init_mmio(sbd, &s->ctl_iomem);
391fb8
-    memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops, s,
391fb8
-                          "fwcfg.data", FW_CFG_DATA_SIZE);
391fb8
-    sysbus_init_mmio(sbd, &s->data_iomem);
391fb8
-    /* In case ctl and data overlap: */
391fb8
-    memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops, s,
391fb8
-                          "fwcfg", FW_CFG_SIZE);
391fb8
+    DeviceState *dev;
391fb8
+    SysBusDevice *sbd;
391fb8
+
391fb8
+    dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
391fb8
+    fw_cfg_init1(dev);
391fb8
+
391fb8
+    sbd = SYS_BUS_DEVICE(dev);
391fb8
+    sysbus_mmio_map(sbd, 0, ctl_addr);
391fb8
+    sysbus_mmio_map(sbd, 1, data_addr);
391fb8
+
391fb8
+    return FW_CFG(dev);
391fb8
 }
391fb8
 
391fb8
-static void fw_cfg_realize(DeviceState *dev, Error **errp)
391fb8
+
391fb8
+FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
391fb8
+                        hwaddr crl_addr, hwaddr data_addr)
391fb8
 {
391fb8
-    FWCfgState *s = FW_CFG(dev);
391fb8
-    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
391fb8
-
391fb8
-    if (s->ctl_iobase + 1 == s->data_iobase) {
391fb8
-        sysbus_add_io(sbd, s->ctl_iobase, &s->comb_iomem);
391fb8
-    } else {
391fb8
-        if (s->ctl_iobase) {
391fb8
-            sysbus_add_io(sbd, s->ctl_iobase, &s->ctl_iomem);
391fb8
-        }
391fb8
-        if (s->data_iobase) {
391fb8
-            sysbus_add_io(sbd, s->data_iobase, &s->data_iomem);
391fb8
-        }
391fb8
+    if (ctl_port + 1 == data_port && crl_addr == 0 && data_addr == 0) {
391fb8
+        return fw_cfg_init_io(ctl_port);
391fb8
+    }
391fb8
+    if (ctl_port == 0 && data_port == 0 && crl_addr != 0 && data_addr != 0) {
391fb8
+        return fw_cfg_init_mem(crl_addr, data_addr);
391fb8
     }
391fb8
+    assert(false);
391fb8
+    return NULL;
391fb8
 }
391fb8
 
391fb8
-static Property fw_cfg_properties[] = {
391fb8
-    DEFINE_PROP_UINT32("ctl_iobase", FWCfgState, ctl_iobase, -1),
391fb8
-    DEFINE_PROP_UINT32("data_iobase", FWCfgState, data_iobase, -1),
391fb8
-    DEFINE_PROP_END_OF_LIST(),
391fb8
-};
391fb8
 
391fb8
 FWCfgState *fw_cfg_find(void)
391fb8
 {
391fb8
@@ -648,23 +655,83 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data)
391fb8
 {
391fb8
     DeviceClass *dc = DEVICE_CLASS(klass);
391fb8
 
391fb8
-    dc->realize = fw_cfg_realize;
391fb8
     dc->reset = fw_cfg_reset;
391fb8
     dc->vmsd = &vmstate_fw_cfg;
391fb8
-    dc->props = fw_cfg_properties;
391fb8
 }
391fb8
 
391fb8
 static const TypeInfo fw_cfg_info = {
391fb8
     .name          = TYPE_FW_CFG,
391fb8
     .parent        = TYPE_SYS_BUS_DEVICE,
391fb8
     .instance_size = sizeof(FWCfgState),
391fb8
-    .instance_init = fw_cfg_initfn,
391fb8
     .class_init    = fw_cfg_class_init,
391fb8
 };
391fb8
 
391fb8
+
391fb8
+static Property fw_cfg_io_properties[] = {
391fb8
+    DEFINE_PROP_UINT32("iobase", FWCfgIoState, iobase, -1),
391fb8
+    DEFINE_PROP_END_OF_LIST(),
391fb8
+};
391fb8
+
391fb8
+static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
391fb8
+{
391fb8
+    FWCfgIoState *s = FW_CFG_IO(dev);
391fb8
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
391fb8
+
391fb8
+    memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops,
391fb8
+                          FW_CFG(s), "fwcfg", FW_CFG_SIZE);
391fb8
+    sysbus_add_io(sbd, s->iobase, &s->comb_iomem);
391fb8
+}
391fb8
+
391fb8
+static void fw_cfg_io_class_init(ObjectClass *klass, void *data)
391fb8
+{
391fb8
+    DeviceClass *dc = DEVICE_CLASS(klass);
391fb8
+
391fb8
+    dc->realize = fw_cfg_io_realize;
391fb8
+    dc->props = fw_cfg_io_properties;
391fb8
+}
391fb8
+
391fb8
+static const TypeInfo fw_cfg_io_info = {
391fb8
+    .name          = TYPE_FW_CFG_IO,
391fb8
+    .parent        = TYPE_FW_CFG,
391fb8
+    .instance_size = sizeof(FWCfgIoState),
391fb8
+    .class_init    = fw_cfg_io_class_init,
391fb8
+};
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
+
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", FW_CFG_DATA_SIZE);
391fb8
+    sysbus_init_mmio(sbd, &s->data_iomem);
391fb8
+}
391fb8
+
391fb8
+static void fw_cfg_mem_class_init(ObjectClass *klass, void *data)
391fb8
+{
391fb8
+    DeviceClass *dc = DEVICE_CLASS(klass);
391fb8
+
391fb8
+    dc->realize = fw_cfg_mem_realize;
391fb8
+}
391fb8
+
391fb8
+static const TypeInfo fw_cfg_mem_info = {
391fb8
+    .name          = TYPE_FW_CFG_MEM,
391fb8
+    .parent        = TYPE_FW_CFG,
391fb8
+    .instance_size = sizeof(FWCfgMemState),
391fb8
+    .class_init    = fw_cfg_mem_class_init,
391fb8
+};
391fb8
+
391fb8
+
391fb8
 static void fw_cfg_register_types(void)
391fb8
 {
391fb8
     type_register_static(&fw_cfg_info);
391fb8
+    type_register_static(&fw_cfg_io_info);
391fb8
+    type_register_static(&fw_cfg_mem_info);
391fb8
 }
391fb8
 
391fb8
 type_init(fw_cfg_register_types)
391fb8
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
391fb8
index 56e1ed7..fcc88ea 100644
391fb8
--- a/include/hw/nvram/fw_cfg.h
391fb8
+++ b/include/hw/nvram/fw_cfg.h
391fb8
@@ -80,6 +80,8 @@ void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data,
391fb8
                          size_t len);
391fb8
 FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
391fb8
                         hwaddr crl_addr, hwaddr data_addr);
391fb8
+FWCfgState *fw_cfg_init_io(uint32_t iobase);
391fb8
+FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr);
391fb8
 
391fb8
 FWCfgState *fw_cfg_find(void);
391fb8
 
391fb8
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
391fb8
index 57ff47f..f2bbaaf 100644
391fb8
--- a/include/qemu/typedefs.h
391fb8
+++ b/include/qemu/typedefs.h
391fb8
@@ -22,6 +22,8 @@ typedef struct DisplayState DisplayState;
391fb8
 typedef struct DisplaySurface DisplaySurface;
391fb8
 typedef struct DriveInfo DriveInfo;
391fb8
 typedef struct EventNotifier EventNotifier;
391fb8
+typedef struct FWCfgIoState FWCfgIoState;
391fb8
+typedef struct FWCfgMemState FWCfgMemState;
391fb8
 typedef struct FWCfgState FWCfgState;
391fb8
 typedef struct HCIInfo HCIInfo;
391fb8
 typedef struct I2CBus I2CBus;
391fb8
-- 
391fb8
2.1.0
391fb8