summaryrefslogtreecommitdiff
path: root/hw/core
diff options
context:
space:
mode:
authorAlistair Francis <alistair.francis@xilinx.com>2016-09-22 18:13:08 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-09-22 18:13:08 +0100
commit3e76099aacb4dae0d37ebf95305369e03d1491e6 (patch)
tree63e50c2aaf0fcf6d34da40cee67d0d89b87c3d81 /hw/core
parentd6ac342a48d50bdceaa43abe2e57854230101d90 (diff)
loader: Allow a custom AddressSpace when loading ROMs
When loading ROMs allow the caller to specify an AddressSpace to use for the load. Signed-off-by: Alistair Francis <alistair.francis@xilinx.com> Message-id: 85f86b94ea94879e7ce8b12e85ac8de26658f7eb.1474331683.git.alistair.francis@xilinx.com Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/core')
-rw-r--r--hw/core/loader.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 6b61f290c3..56c593ead7 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -777,6 +777,7 @@ struct Rom {
uint8_t *data;
MemoryRegion *mr;
+ AddressSpace *as;
int isrom;
char *fw_dir;
char *fw_file;
@@ -788,6 +789,12 @@ struct Rom {
static FWCfgState *fw_cfg;
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
+static inline bool rom_order_compare(Rom *rom, Rom *item)
+{
+ return (rom->as > item->as) ||
+ (rom->as == item->as && rom->addr >= item->addr);
+}
+
static void rom_insert(Rom *rom)
{
Rom *item;
@@ -796,10 +803,16 @@ static void rom_insert(Rom *rom)
hw_error ("ROM images must be loaded at startup\n");
}
- /* list is ordered by load address */
+ /* The user didn't specify an address space, this is the default */
+ if (!rom->as) {
+ rom->as = &address_space_memory;
+ }
+
+ /* List is ordered by load address in the same address space */
QTAILQ_FOREACH(item, &roms, next) {
- if (rom->addr >= item->addr)
+ if (rom_order_compare(rom, item)) {
continue;
+ }
QTAILQ_INSERT_BEFORE(item, rom, next);
return;
}
@@ -833,16 +846,25 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name)
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex,
- bool option_rom, MemoryRegion *mr)
+ bool option_rom, MemoryRegion *mr,
+ AddressSpace *as)
{
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
Rom *rom;
int rc, fd = -1;
char devpath[100];
+ if (as && mr) {
+ fprintf(stderr, "Specifying an Address Space and Memory Region is " \
+ "not valid when loading a rom\n");
+ /* We haven't allocated anything so we don't need any cleanup */
+ return -1;
+ }
+
rom = g_malloc0(sizeof(*rom));
rom->name = g_strdup(file);
rom->path = qemu_find_file(QEMU_FILE_TYPE_BIOS, rom->name);
+ rom->as = as;
if (rom->path == NULL) {
rom->path = g_strdup(file);
}
@@ -969,7 +991,7 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
* memory ownership of "data", so we don't have to allocate and copy the buffer.
*/
int rom_add_elf_program(const char *name, void *data, size_t datasize,
- size_t romsize, hwaddr addr)
+ size_t romsize, hwaddr addr, AddressSpace *as)
{
Rom *rom;
@@ -979,18 +1001,19 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize,
rom->datasize = datasize;
rom->romsize = romsize;
rom->data = data;
+ rom->as = as;
rom_insert(rom);
return 0;
}
int rom_add_vga(const char *file)
{
- return rom_add_file(file, "vgaroms", 0, -1, true, NULL);
+ return rom_add_file(file, "vgaroms", 0, -1, true, NULL, NULL);
}
int rom_add_option(const char *file, int32_t bootindex)
{
- return rom_add_file(file, "genroms", 0, bootindex, true, NULL);
+ return rom_add_file(file, "genroms", 0, bootindex, true, NULL, NULL);
}
static void rom_reset(void *unused)
@@ -1008,8 +1031,8 @@ static void rom_reset(void *unused)
void *host = memory_region_get_ram_ptr(rom->mr);
memcpy(host, rom->data, rom->datasize);
} else {
- cpu_physical_memory_write_rom(&address_space_memory,
- rom->addr, rom->data, rom->datasize);
+ cpu_physical_memory_write_rom(rom->as, rom->addr, rom->data,
+ rom->datasize);
}
if (rom->isrom) {
/* rom needs to be written only once */
@@ -1031,12 +1054,13 @@ int rom_check_and_register_reset(void)
hwaddr addr = 0;
MemoryRegionSection section;
Rom *rom;
+ AddressSpace *as = NULL;
QTAILQ_FOREACH(rom, &roms, next) {
if (rom->fw_file) {
continue;
}
- if (addr > rom->addr) {
+ if ((addr > rom->addr) && (as == rom->as)) {
fprintf(stderr, "rom: requested regions overlap "
"(rom %s. free=0x" TARGET_FMT_plx
", addr=0x" TARGET_FMT_plx ")\n",
@@ -1049,6 +1073,7 @@ int rom_check_and_register_reset(void)
rom->addr, 1);
rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
memory_region_unref(section.mr);
+ as = rom->as;
}
qemu_register_reset(rom_reset, NULL);
roms_loaded = 1;