From: "Philippe Mathieu-Daudé" <f4bug@amsat.org>
To: qemu-devel@nongnu.org
Cc: "Stephen Checkoway" <stephen.checkoway@oberlin.edu>,
qemu-block@nongnu.org,
"Richard Henderson" <richard.henderson@linaro.org>,
"Philippe Mathieu-Daudé" <f4bug@amsat.org>,
"Peter Xu" <peterx@redhat.com>,
"David Edmondson" <david.edmondson@oracle.com>,
qemu-arm@nongnu.org, "Paolo Bonzini" <pbonzini@redhat.com>
Subject: [RFC PATCH v2 1/7] hw/misc: Add device to help managing aliased memory regions
Date: Mon, 19 Apr 2021 11:43:23 +0200 [thread overview]
Message-ID: <20210419094329.1402767-2-f4bug@amsat.org> (raw)
In-Reply-To: <20210419094329.1402767-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>
---
Not really RFC, simply that I'v to add the technical description,
but I'd like to know if there could be a possibility to not accept
this device (because I missed something) before keeping working on
it. So far it is only used in hobbyist boards.
Cc: Peter Xu <peterx@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
---
include/hw/misc/aliased_region.h | 87 ++++++++++++++++++++
hw/misc/aliased_region.c | 132 +++++++++++++++++++++++++++++++
MAINTAINERS | 6 ++
hw/misc/Kconfig | 3 +
hw/misc/meson.build | 1 +
5 files changed, 229 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..3132276af29
--- /dev/null
+++ b/hw/misc/aliased_region.c
@@ -0,0 +1,132 @@
+/*
+ * 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/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 36055f14c59..151c342e338 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2095,6 +2095,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.3
next prev parent reply other threads:[~2021-04-19 9:45 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-19 9:43 [PATCH v2 0/7] hw/misc: Add memory_region_add_subregion_aliased() helper [pflash part] Philippe Mathieu-Daudé
2021-04-19 9:43 ` Philippe Mathieu-Daudé [this message]
2021-04-22 1:33 ` [RFC PATCH v2 1/7] hw/misc: Add device to help managing aliased memory regions Richard Henderson
2021-07-06 21:24 ` Philippe Mathieu-Daudé
2021-04-19 9:43 ` [PATCH v2 2/7] hw/arm/musicpal: Open-code pflash_cfi02_register() call Philippe Mathieu-Daudé
2021-04-22 1:37 ` Richard Henderson
2021-04-19 9:43 ` [PATCH v2 3/7] hw/arm/musicpal: Map flash using memory_region_add_subregion_aliased() Philippe Mathieu-Daudé
2021-04-22 1:41 ` Richard Henderson
2021-04-19 9:43 ` [PATCH v2 4/7] hw/arm/digic: Open-code pflash_cfi02_register() call Philippe Mathieu-Daudé
2021-04-22 1:42 ` Richard Henderson
2021-04-19 9:43 ` [PATCH v2 5/7] hw/arm/digic: Map flash using memory_region_add_subregion_aliased() Philippe Mathieu-Daudé
2021-04-22 1:43 ` Richard Henderson
2021-04-19 9:43 ` [PATCH v2 6/7] hw/block/pflash_cfi02: Remove pflash_setup_mappings() Philippe Mathieu-Daudé
2021-04-22 1:47 ` Richard Henderson
2021-04-19 9:43 ` [PATCH v2 7/7] hw/block/pflash_cfi02: Simplify pflash_cfi02_register() prototype Philippe Mathieu-Daudé
2021-04-22 1:48 ` Richard Henderson
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=20210419094329.1402767-2-f4bug@amsat.org \
--to=f4bug@amsat.org \
--cc=david.edmondson@oracle.com \
--cc=pbonzini@redhat.com \
--cc=peterx@redhat.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=stephen.checkoway@oberlin.edu \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).