All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Philippe Mathieu-Daudé" <f4bug@amsat.org>
To: qemu-devel@nongnu.org
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
	"Mark Cave-Ayland" <mark.cave-ayland@ilande.co.uk>,
	"Alistair Francis" <alistair@alistair23.me>,
	"Richard Henderson" <richard.henderson@linaro.org>,
	"Philippe Mathieu-Daudé" <f4bug@amsat.org>,
	"Laurent Vivier" <laurent@vivier.eu>,
	qemu-arm@nongnu.org, qemu-ppc@nongnu.org,
	"Edgar E. Iglesias" <edgar.iglesias@gmail.com>,
	"David Gibson" <david@gibson.dropbear.id.au>
Subject: [RFC PATCH-for-6.1 01/10] hw/misc: Add device to help managing aliased memory regions
Date: Fri, 26 Mar 2021 01:27:19 +0100	[thread overview]
Message-ID: <20210326002728.1069834-2-f4bug@amsat.org> (raw)
In-Reply-To: <20210326002728.1069834-1-f4bug@amsat.org>

// TODO explain here how buses work? when some address lines are
// not bound we get memory aliasing, high addresses are masked.
// etc...

Add a helper to manage this use case easily.

For example a having @span_size = @region_size / 4 we get such mapping:

          ^-----------^
          |           |
          |           |
          | +-------+ |                 +---------+          <--+
          |           |                 +---------+             |
          |           |                 |         |             |
          |           |   +-----------> | alias#3 |             |
          |           |   |             |         |             |
          |           |   |             +---------+             |
          |           |   |             +---------+             |
          |           |   |             |         |             |
          |           |   |   +-------> | alias#2 |             |
          |           |   |   |         |         |             |region
          | container |   |   |         +---------+             | size
          |           |   |   |         +---------+             |
          |           |   |   |         |         |             |
          |           |   |   |  +----> | alias#1 |             |
          |           |   |   |  |      |         |             |
          |           |   |   |  |      +---------+  <--+       |
          |           | +-+---+--+--+   +---------+     |       |
          |           | |           |   |         |     |span   |
          |           | | subregion +-> | alias#0 |     |size   |
   offset |           | |           |   |         |     |       |
   +----> | +-------+ | +-----------+   +---------+  <--+    <--+
   |      |           |
   |      |           |
   |      |           |
   |      |           |
   |      |           |
   |      ^-----------^

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 include/hw/misc/aliased_region.h |  87 ++++++++++++++++++++
 hw/misc/aliased_region.c         | 133 +++++++++++++++++++++++++++++++
 MAINTAINERS                      |   6 ++
 hw/misc/Kconfig                  |   3 +
 hw/misc/meson.build              |   1 +
 5 files changed, 230 insertions(+)
 create mode 100644 include/hw/misc/aliased_region.h
 create mode 100644 hw/misc/aliased_region.c

diff --git a/include/hw/misc/aliased_region.h b/include/hw/misc/aliased_region.h
new file mode 100644
index 00000000000..0ce0d5d1cef
--- /dev/null
+++ b/include/hw/misc/aliased_region.h
@@ -0,0 +1,87 @@
+/*
+ * Aliased memory regions
+ *
+ * Copyright (c) 2018  Philippe Mathieu-Daudé <f4bug@amsat.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_ALIASED_REGION_H
+#define HW_MISC_ALIASED_REGION_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+#define TYPE_ALIASED_REGION "aliased-memory-region"
+OBJECT_DECLARE_SIMPLE_TYPE(AliasedRegionState, ALIASED_REGION)
+
+struct AliasedRegionState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    MemoryRegion container;
+    uint64_t region_size;
+    uint64_t span_size;
+    MemoryRegion *mr;
+
+    struct {
+        size_t count;
+        MemoryRegion *alias;
+    } mem;
+};
+
+/**
+ * memory_region_add_subregion_aliased:
+ * @container: the #MemoryRegion to contain the aliased subregions.
+ * @offset: the offset relative to @container where the aliased subregion
+ *          are added.
+ * @region_size: size of the region containing the aliased subregions.
+ * @subregion: the subregion to be aliased.
+ * @span_size: size between each aliased subregion
+ *
+ * This utility function creates and maps an instance of aliased-memory-region,
+ * which is a dummy device of a single region which simply contains multiple
+ * aliases of the provided @subregion, spanned over the @region_size every
+ * @span_size. The device is mapped at @offset within @container.
+ *
+ * For example a having @span_size = @region_size / 4 we get such mapping:
+ *
+ *               +-----------+
+ *               |           |
+ *               |           |
+ *               | +-------+ |                 +---------+          <--+
+ *               |           |                 +---------+             |
+ *               |           |                 |         |             |
+ *               |           |   +-----------> | alias#3 |             |
+ *               |           |   |             |         |             |
+ *               |           |   |             +---------+             |
+ *               |           |   |             +---------+             |
+ *               |           |   |             |         |             |
+ *               |           |   |   +-------> | alias#2 |             |
+ *               |           |   |   |         |         |             |region
+ *               | container |   |   |         +---------+             | size
+ *               |           |   |   |         +---------+             |
+ *               |           |   |   |         |         |             |
+ *               |           |   |   |  +----> | alias#1 |             |
+ *               |           |   |   |  |      |         |             |
+ *               |           |   |   |  |      +---------+  <--+       |
+ *               |           | +-+---+--+--+   +---------+     |       |
+ *               |           | |           |   |         |     |span   |
+ *               |           | | subregion +-> | alias#0 |     |size   |
+ *        offset |           | |           |   |         |     |       |
+ *        +----> | +-------+ | +-----------+   +---------+  <--+    <--+
+ *        |      |           |
+ *        |      |           |
+ *        |      |           |
+ *        |      |           |
+ *        |      |           |
+ *        +      +-----------+
+ */
+void memory_region_add_subregion_aliased(MemoryRegion *container,
+                                         hwaddr offset,
+                                         uint64_t region_size,
+                                         MemoryRegion *subregion,
+                                         uint64_t span_size);
+
+#endif
diff --git a/hw/misc/aliased_region.c b/hw/misc/aliased_region.c
new file mode 100644
index 00000000000..8fcc63f2648
--- /dev/null
+++ b/hw/misc/aliased_region.c
@@ -0,0 +1,133 @@
+/*
+ * Aliased memory regions
+ *
+ * Copyright (c) 2018  Philippe Mathieu-Daudé <f4bug@amsat.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/misc/aliased_region.h"
+#include "hw/qdev-properties.h"
+
+static void aliased_mem_realize(AliasedRegionState *s, const char *mr_name)
+{
+    uint64_t subregion_size;
+    int subregion_bits;
+
+    memory_region_init(&s->container, OBJECT(s), mr_name, s->region_size);
+
+    subregion_bits = 64 - clz64(s->span_size - 1);
+    s->mem.count = s->region_size >> subregion_bits;
+    assert(s->mem.count > 1);
+    subregion_size = 1ULL << subregion_bits;
+
+    s->mem.alias = g_new(MemoryRegion, s->mem.count);
+    for (size_t i = 0; i < s->mem.count; i++) {
+        g_autofree char *name = g_strdup_printf("%s [#%zu/%zu]",
+                                                memory_region_name(s->mr),
+                                                i, s->mem.count);
+        memory_region_init_alias(&s->mem.alias[i], OBJECT(s), name,
+                                 s->mr, 0, s->span_size);
+        memory_region_add_subregion(&s->container, i * subregion_size,
+                                    &s->mem.alias[i]);
+    }
+}
+
+static void aliased_mr_realize(DeviceState *dev, Error **errp)
+{
+    AliasedRegionState *s = ALIASED_REGION(dev);
+    g_autofree char *name = NULL, *span = NULL;
+
+    if (s->region_size == 0) {
+        error_setg(errp, "property 'region-size' not specified or zero");
+        return;
+    }
+
+    if (s->mr == NULL) {
+        error_setg(errp, "property 'iomem' not specified");
+        return;
+    }
+
+    if (!s->span_size) {
+        s->span_size = pow2ceil(memory_region_size(s->mr));
+    } else if (!is_power_of_2(s->span_size)) {
+        error_setg(errp, "property 'span-size' must be a power of 2");
+        return;
+    }
+
+    span = size_to_str(s->span_size);
+    name = g_strdup_printf("masked %s [span of %s]",
+                           memory_region_name(s->mr), span);
+    aliased_mem_realize(s, name);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
+}
+
+static void aliased_mr_unrealize(DeviceState *dev)
+{
+    AliasedRegionState *s = ALIASED_REGION(dev);
+
+    g_free(s->mem.alias);
+}
+
+static Property aliased_mr_properties[] = {
+    DEFINE_PROP_UINT64("region-size", AliasedRegionState, region_size, 0),
+    DEFINE_PROP_UINT64("span-size", AliasedRegionState, span_size, 0),
+    DEFINE_PROP_LINK("iomem", AliasedRegionState, mr,
+                     TYPE_MEMORY_REGION, MemoryRegion *),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void aliased_mr_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = aliased_mr_realize;
+    dc->unrealize = aliased_mr_unrealize;
+    /* Reason: needs to be wired up to work */
+    dc->user_creatable = false;
+    device_class_set_props(dc, aliased_mr_properties);
+}
+
+static const TypeInfo aliased_mr_info = {
+    .name = TYPE_ALIASED_REGION,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AliasedRegionState),
+    .class_init = aliased_mr_class_init,
+};
+
+static void aliased_mr_register_types(void)
+{
+    type_register_static(&aliased_mr_info);
+}
+
+type_init(aliased_mr_register_types)
+
+void memory_region_add_subregion_aliased(MemoryRegion *container,
+                                         hwaddr offset,
+                                         uint64_t region_size,
+                                         MemoryRegion *subregion,
+                                         uint64_t span_size)
+{
+    DeviceState *dev;
+
+    if (!region_size) {
+        region_size = pow2ceil(memory_region_size(container));
+    } else {
+        assert(region_size <= memory_region_size(container));
+    }
+
+    dev = qdev_new(TYPE_ALIASED_REGION);
+    qdev_prop_set_uint64(dev, "region-size", region_size);
+    qdev_prop_set_uint64(dev, "span-size", span_size);
+    object_property_set_link(OBJECT(dev), "iomem", OBJECT(subregion),
+                             &error_abort);
+    sysbus_realize(SYS_BUS_DEVICE(dev), &error_abort);
+
+    memory_region_add_subregion(container, offset,
+                                sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
+}
diff --git a/MAINTAINERS b/MAINTAINERS
index 554be84b321..f82ffd50a91 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2097,6 +2097,12 @@ S: Maintained
 F: include/hw/misc/empty_slot.h
 F: hw/misc/empty_slot.c
 
+Aliased memory region
+M: Philippe Mathieu-Daudé <f4bug@amsat.org>
+S: Maintained
+F: include/hw/misc/aliased_region.h
+F: hw/misc/aliased_region.c
+
 Standard VGA
 M: Gerd Hoffmann <kraxel@redhat.com>
 S: Maintained
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index c71ed258204..ca51b99989e 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -151,6 +151,9 @@ config AUX
 config UNIMP
     bool
 
+config ALIASED_REGION
+    bool
+
 config LED
     bool
 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 21034dc60a8..e65541b835f 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -12,6 +12,7 @@
 softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c'))
 softmmu_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c'))
 softmmu_ss.add(when: 'CONFIG_EMPTY_SLOT', if_true: files('empty_slot.c'))
+softmmu_ss.add(when: 'CONFIG_ALIASED_REGION', if_true: files('aliased_region.c'))
 softmmu_ss.add(when: 'CONFIG_LED', if_true: files('led.c'))
 softmmu_ss.add(when: 'CONFIG_PVPANIC_COMMON', if_true: files('pvpanic.c'))
 
-- 
2.26.2



  reply	other threads:[~2021-03-26  0:31 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-26  0:27 [RFC PATCH-for-6.1 00/10] hw/misc: Add memory_region_add_subregion_aliased() helper Philippe Mathieu-Daudé
2021-03-26  0:27 ` Philippe Mathieu-Daudé [this message]
2021-03-26  0:27 ` [PATCH-for-6.1 02/10] hw/arm/musicpal: Open-code pflash_cfi02_register() call Philippe Mathieu-Daudé
2021-03-26  0:27 ` [RFC PATCH-for-6.1 03/10] hw/arm/musicpal: Map flash using memory_region_add_subregion_aliased() Philippe Mathieu-Daudé
2021-03-26 22:49   ` Philippe Mathieu-Daudé
2021-03-26  0:27 ` [PATCH-for-6.1 04/10] hw/arm/digic: Open-code pflash_cfi02_register() call Philippe Mathieu-Daudé
2021-03-26  0:27 ` [RFC PATCH-for-6.1 05/10] hw/arm/digic: Map flash using memory_region_add_subregion_aliased() Philippe Mathieu-Daudé
2021-03-26  0:27 ` [PATCH-for-6.1 06/10] hw/block/pflash_cfi02: Remove pflash_setup_mappings() Philippe Mathieu-Daudé
2021-03-29  4:11   ` David Gibson
2021-03-26  0:27 ` [PATCH-for-6.1 07/10] hw/block/pflash_cfi02: Simplify pflash_cfi02_register() prototype Philippe Mathieu-Daudé
2021-03-29  4:12   ` David Gibson
2021-03-26  0:27 ` [RFC PATCH-for-6.1 08/10] hw/misc/aliased_region: Simplify aliased I/O regions Philippe Mathieu-Daudé
2021-03-26  0:27 ` [PATCH-for-6.1 09/10] hw/m68k/q800: Add MacIO container Philippe Mathieu-Daudé
2021-03-26  0:27 ` [RFC PATCH-for-6.1 10/10] hw/m68k/q800: Map MacIO using memory_region_add_subregion_aliased() Philippe Mathieu-Daudé
2021-03-26 12:58 ` [RFC PATCH-for-6.1 00/10] hw/misc: Add memory_region_add_subregion_aliased() helper Richard Henderson
2021-03-27 21:45 ` Mark Cave-Ayland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210326002728.1069834-2-f4bug@amsat.org \
    --to=f4bug@amsat.org \
    --cc=alistair@alistair23.me \
    --cc=david@gibson.dropbear.id.au \
    --cc=edgar.iglesias@gmail.com \
    --cc=laurent@vivier.eu \
    --cc=mark.cave-ayland@ilande.co.uk \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=richard.henderson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.