Update tt-atlantis to, when the RCPU is enabled and bootrom binary is
provided, load the provided bootrom binary for the RCPU to execute.
This adds a tt-atlantis machine property 'bootrom' that takes a file
name. qemu_find_file() tries the filename before the search path, so both
full file paths and filenames relative to -L work:
-M tt-atlantis,rcpu=on,bootrom=out/bootrom.bin
Signed-off-by: Portia Stephens <[email protected]>
---
hw/riscv/tt_atlantis.c | 63 ++++++++++++++++++++++++++++++++--
include/hw/riscv/tt_atlantis.h | 4 +++
2 files changed, 64 insertions(+), 3 deletions(-)
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index f778091e91..f3e35c63ea 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -9,6 +9,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/cutils.h"
+#include "qemu/datadir.h"
#include "qemu/error-report.h"
#include "qemu/guest-random.h"
#include "qemu/units.h"
@@ -663,15 +664,36 @@ static void tt_rcpu_cluster_realize(DeviceState *dev,
Error **errp)
create_unimplemented_devices(OBJECT(rc), &rc->memory, rcpu_unimp_dev);
- /* no bootrom image is provided, don't let the core run */
- CPU(&rc->cpus.harts[0])->start_powered_off = true;
+ if (rc->bootrom_image) {
+ ssize_t rom_size;
+
+ g_autofree char *rom_file = qemu_find_file(QEMU_FILE_TYPE_BIOS,
rc->bootrom_image);
+ if (!rom_file) {
+ error_setg(errp, "could not find bootrom image '%s'",
rc->bootrom_image);
+ return;
+ }
+
+ rom_size = load_image_mr(rom_file, &rc->bootrom);
+ if (rom_size <= 0) {
+ error_setg(errp, "could not load bootrom image '%s'",
rc->bootrom_image);
+ return;
+ }
+ } else {
+ /* no bootrom image is provided, don't let the core run */
+ CPU(&rc->cpus.harts[0])->start_powered_off = true;
+ }
}
+static const Property tt_rcpu_cluster_props[] = {
+ DEFINE_PROP_STRING("bootrom-name", TTRCPUClusterState, bootrom_image),
+};
+
static void tt_rcpu_cluster_class_init(ObjectClass *oc, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = tt_rcpu_cluster_realize;
+ device_class_set_props(dc, tt_rcpu_cluster_props);
/* The cluster must be instantiated by a machine or SoC */
dc->user_creatable = false;
}
@@ -830,6 +852,13 @@ static void tt_atlantis_soc_realize(DeviceState *dev,
Error **errp)
if (s->has_rcpu) {
/* Only create the RCPU if it is enabled */
object_initialize_child(OBJECT(s), "rcpu", &s->rcpu,
TYPE_TT_RCPU_CLUSTER);
+
+ if (s->rcpu_bootrom_image) {
+ object_property_set_str(OBJECT(rc), "bootrom-name",
+ s->rcpu_bootrom_image,
+ &error_abort);
+ }
+
if (!qdev_realize(DEVICE(&s->rcpu), NULL, errp)) {
return;
}
@@ -1008,7 +1037,8 @@ static void tt_atlantis_soc_realize(DeviceState *dev,
Error **errp)
static const Property tt_atlantis_soc_props[] = {
DEFINE_PROP_LINK("dram", TTAtlantisSoCState, dram,
TYPE_MEMORY_REGION, MemoryRegion *),
- DEFINE_PROP_BOOL("has-rcpu", TTAtlantisSoCState, has_rcpu, false)
+ DEFINE_PROP_BOOL("has-rcpu", TTAtlantisSoCState, has_rcpu, false),
+ DEFINE_PROP_STRING("bootrom-name", TTAtlantisSoCState, rcpu_bootrom_image)
};
static void tt_atlantis_soc_class_init(ObjectClass *oc, const void *data)
@@ -1060,6 +1090,13 @@ static void tt_atlantis_machine_init(MachineState
*machine)
num_asc_harts,
&error_abort);
+ if (ams->has_rcpu && ams->rcpu_bootrom_image) {
+ /* Set the RCPU bootrom file name provided on the command line */
+ object_property_set_str(OBJECT(s), "bootrom-name",
+ ams->rcpu_bootrom_image,
+ &error_abort);
+ }
+
object_property_set_link(OBJECT(s), "dram", OBJECT(machine->ram),
&error_abort);
object_property_set_bool(OBJECT(&ams->soc), "has-rcpu", ams->has_rcpu,
@@ -1096,6 +1133,22 @@ static void tt_atlantis_machine_set_rcpu(Object *obj,
bool value, Error **errp)
s->has_rcpu = value;
}
+static char *tt_atlantis_get_bootrom(Object *obj, Error **errp)
+{
+ TTAtlantisState *s = TT_ATLANTIS_MACHINE(obj);
+
+ return g_strdup(s->rcpu_bootrom_image);
+}
+
+static void tt_atlantis_set_bootrom(Object *obj, const char *value,
+ Error **errp)
+{
+ TTAtlantisState *s = TT_ATLANTIS_MACHINE(obj);
+
+ g_free(s->rcpu_bootrom_image);
+ s->rcpu_bootrom_image = g_strdup(value);
+}
+
static void tt_atlantis_machine_class_init(ObjectClass *oc, const void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -1123,6 +1176,10 @@ static void tt_atlantis_machine_class_init(ObjectClass
*oc, const void *data)
"Set to enable/disable modeling the
RCPU.");
object_property_set_default_bool(prop, false);
+ object_class_property_add_str(oc, "bootrom",
+ tt_atlantis_get_bootrom,
+ tt_atlantis_set_bootrom);
+ object_class_property_set_description(oc, "bootrom", "RCPU bootrom image");
}
static const TypeInfo tt_atlantis_types[] = {
diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
index 5a200410f3..e9cc147060 100644
--- a/include/hw/riscv/tt_atlantis.h
+++ b/include/hw/riscv/tt_atlantis.h
@@ -64,6 +64,8 @@ struct TTRCPUClusterState {
CPUClusterState cluster;
MemoryRegion bootrom;
MemoryRegion sram;
+
+ char *bootrom_image;
};
struct TTAtlantisSoCState {
@@ -84,6 +86,7 @@ struct TTAtlantisSoCState {
TTAtlantisPRCMState prcm[TT_ATL_NUM_PRCM];
bool has_rcpu; /* Enable RCPU */
+ char *rcpu_bootrom_image; /* RCPU boot ROM image */
};
struct TTAtlantisState {
@@ -96,6 +99,7 @@ struct TTAtlantisState {
TTAtlantisSoCState soc;
bool has_rcpu; /* Enable RCPU */
+ char *rcpu_bootrom_image; /* RCPU boot ROM image */
};
enum {
--
2.43.0