All of lore.kernel.org
 help / color / mirror / Atom feed
From: Shawn Rutledge <lists@ecloud.org>
To: qemu-devel@nongnu.org
Subject: [PATCH] hw/riscv/virt: add dram-base machine property
Date: Thu, 30 Jul 2026 11:41:47 +0200	[thread overview]
Message-ID: <amscWwQvYUftUYW8@zen> (raw)

The 'virt' RISC-V machine hardcodes its DRAM base to 0x80000000.
Real-world RISC-V SoCs put DRAM elsewhere (SpacemiT K1 at 0x40000000,
SpacemiT K3 at 0x100000000, etc.), which forces ports that target
those boards to build separate kernels for QEMU testing.

Add a 'dram-base' string property that lets users move VIRT_DRAM up
without rebuilding QEMU.  Values must be 2 MiB-aligned and at or
above the default 0x80000000 to avoid colliding with statically-
placed MMIO regions (PCIE_MMIO ends at 0x80000000).  Lower bases
would also require moving PCIE_MMIO/IMSIC/etc. and are rejected with
an explicit error pointing at the cause.

Example:
  qemu-system-riscv64 -machine virt,dram-base=0x100000000 -m 6G ...
runs OpenSBI at firmware base 0x100000000, matching K3 memory layout.

Signed-off-by: Shawn Rutledge <s@ecloud.org>
---
 hw/riscv/virt.c         | 59 ++++++++++++++++++++++++++++++++++++++++-
 include/hw/riscv/virt.h |  2 ++
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 51bac47a91..6ccc98842f 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -20,6 +20,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/units.h"
+#include "qemu/cutils.h"
 #include "qemu/error-report.h"
 #include "qemu/guest-random.h"
 #include "qapi/error.h"
@@ -1307,7 +1308,13 @@ static void virt_machine_init(MachineState *machine)
     int i, base_hartid, hart_count;
     int socket_count = riscv_socket_count(machine);
 
-    s->memmap = virt_memmap;
+    if (s->dram_base) {
+        s->memmap_storage = g_memdup2(virt_memmap, sizeof(virt_memmap));
+        s->memmap_storage[VIRT_DRAM].base = s->dram_base;
+        s->memmap = s->memmap_storage;
+    } else {
+        s->memmap = virt_memmap;
+    }
 
     /* Check socket count limit */
     if (VIRT_SOCKETS_MAX < socket_count) {
@@ -1545,6 +1552,7 @@ static void virt_machine_instance_finalize(Object *obj)
     }
     g_free(s->oem_id);
     g_free(s->oem_table_id);
+    g_free(s->memmap_storage);
 }
 
 static void virt_machine_instance_init(Object *obj)
@@ -1616,6 +1624,46 @@ static void virt_set_aia(Object *obj, const char *val, Error **errp)
     }
 }
 
+static char *virt_get_dram_base(Object *obj, Error **errp)
+{
+    RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
+    uint64_t val = s->dram_base ? s->dram_base : virt_memmap[VIRT_DRAM].base;
+
+    return g_strdup_printf("0x%" PRIx64, val);
+}
+
+static void virt_set_dram_base(Object *obj, const char *val, Error **errp)
+{
+    RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
+    const char *endptr;
+    uint64_t base;
+
+    if (qemu_strtou64(val, &endptr, 0, &base) < 0 || *endptr != '\0') {
+        error_setg(errp, "Invalid dram-base value '%s'", val);
+        return;
+    }
+    /*
+     * DRAM must clear all statically-placed MMIO regions in virt_memmap[]
+     * (PCIE_MMIO ends at 0x80000000) and be 2 MiB-aligned so a standard
+     * OpenSBI + kernel layout (firmware at base, kernel at base+0x200000)
+     * fits.  Values below the default base would collide with on-board
+     * MMIO and are rejected.
+     */
+    if (base < virt_memmap[VIRT_DRAM].base) {
+        error_setg(errp,
+                   "dram-base 0x%" PRIx64 " is below default 0x%" PRIx64
+                   "; would collide with static MMIO regions",
+                   base, (uint64_t)virt_memmap[VIRT_DRAM].base);
+        return;
+    }
+    if (base & (2 * MiB - 1)) {
+        error_setg(errp, "dram-base 0x%" PRIx64 " must be 2 MiB-aligned",
+                   base);
+        return;
+    }
+    s->dram_base = base;
+}
+
 static bool virt_get_aclint(Object *obj, Error **errp)
 {
     RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
@@ -1744,6 +1792,15 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
 #endif
 
+    object_class_property_add_str(oc, "dram-base", virt_get_dram_base,
+                                  virt_set_dram_base);
+    object_class_property_set_description(oc, "dram-base",
+                                          "Base physical address of DRAM "
+                                          "(default 0x80000000). Must be "
+                                          "2 MiB-aligned and at or above "
+                                          "the default to avoid colliding "
+                                          "with statically-placed MMIO.");
+
     object_class_property_add_bool(oc, "aclint", virt_get_aclint,
                                    virt_set_aclint);
     object_class_property_set_description(oc, "aclint",
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 36a2def410..be8a4ac049 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -61,6 +61,8 @@ struct RISCVVirtState {
     char *oem_table_id;
     OnOffAuto acpi;
     const MemMapEntry *memmap;
+    MemMapEntry *memmap_storage; /* g_malloc'd copy when dram-base override is set */
+    uint64_t dram_base;          /* 0 = use compiled-in default (0x80000000) */
     struct GPEXHost *gpex_host;
     OnOffAuto iommu_sys;
     uint16_t pci_iommu_bdf;
-- 
2.55.0



                 reply	other threads:[~2026-07-30  9:42 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=amscWwQvYUftUYW8@zen \
    --to=lists@ecloud.org \
    --cc=qemu-devel@nongnu.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.