aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/core/qdev-properties-system.c31
-rw-r--r--hw/intc/sifive_plic.h83
-rw-r--r--hw/misc/sifive_u_otp.c95
-rw-r--r--hw/riscv/boot.c56
-rw-r--r--hw/riscv/opentitan.c3
-rw-r--r--hw/riscv/sifive_e.c3
-rw-r--r--hw/riscv/sifive_u.c28
-rw-r--r--hw/riscv/spike.c11
-rw-r--r--hw/riscv/virt.c11
9 files changed, 180 insertions, 141 deletions
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index 49bdd12581..b81a4e8d14 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -30,6 +30,7 @@
#include "sysemu/blockdev.h"
#include "net/net.h"
#include "hw/pci/pci.h"
+#include "util/block-helpers.h"
static bool check_prop_still_unset(DeviceState *dev, const char *name,
const void *old_val, const char *new_val,
@@ -576,16 +577,6 @@ const PropertyInfo qdev_prop_losttickpolicy = {
/* --- blocksize --- */
-/* lower limit is sector size */
-#define MIN_BLOCK_SIZE 512
-#define MIN_BLOCK_SIZE_STR "512 B"
-/*
- * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and
- * matches qcow2 cluster size limit
- */
-#define MAX_BLOCK_SIZE (2 * MiB)
-#define MAX_BLOCK_SIZE_STR "2 MiB"
-
static void set_blocksize(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -593,6 +584,7 @@ static void set_blocksize(Object *obj, Visitor *v, const char *name,
Property *prop = opaque;
uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
uint64_t value;
+ Error *local_err = NULL;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
@@ -602,24 +594,11 @@ static void set_blocksize(Object *obj, Visitor *v, const char *name,
if (!visit_type_size(v, name, &value, errp)) {
return;
}
- /* value of 0 means "unset" */
- if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) {
- error_setg(errp,
- "Property %s.%s doesn't take value %" PRIu64
- " (minimum: " MIN_BLOCK_SIZE_STR
- ", maximum: " MAX_BLOCK_SIZE_STR ")",
- dev->id ? : "", name, value);
- return;
- }
-
- /* We rely on power-of-2 blocksizes for bitmasks */
- if ((value & (value - 1)) != 0) {
- error_setg(errp,
- "Property %s.%s doesn't take value '%" PRId64 "', "
- "it's not a power of 2", dev->id ?: "", name, (int64_t)value);
+ check_block_size(dev->id ? : "", name, value, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
return;
}
-
*ptr = value;
}
diff --git a/hw/intc/sifive_plic.h b/hw/intc/sifive_plic.h
deleted file mode 100644
index b75b1f145d..0000000000
--- a/hw/intc/sifive_plic.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * SiFive PLIC (Platform Level Interrupt Controller) interface
- *
- * Copyright (c) 2017 SiFive, Inc.
- *
- * This provides a RISC-V PLIC device
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2 or later, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef HW_SIFIVE_PLIC_H
-#define HW_SIFIVE_PLIC_H
-
-#include "hw/sysbus.h"
-#include "qom/object.h"
-
-#define TYPE_SIFIVE_PLIC "riscv.sifive.plic"
-
-typedef struct SiFivePLICState SiFivePLICState;
-DECLARE_INSTANCE_CHECKER(SiFivePLICState, SIFIVE_PLIC,
- TYPE_SIFIVE_PLIC)
-
-typedef enum PLICMode {
- PLICMode_U,
- PLICMode_S,
- PLICMode_H,
- PLICMode_M
-} PLICMode;
-
-typedef struct PLICAddr {
- uint32_t addrid;
- uint32_t hartid;
- PLICMode mode;
-} PLICAddr;
-
-struct SiFivePLICState {
- /*< private >*/
- SysBusDevice parent_obj;
-
- /*< public >*/
- MemoryRegion mmio;
- uint32_t num_addrs;
- uint32_t num_harts;
- uint32_t bitfield_words;
- PLICAddr *addr_config;
- uint32_t *source_priority;
- uint32_t *target_priority;
- uint32_t *pending;
- uint32_t *claimed;
- uint32_t *enable;
-
- /* config */
- char *hart_config;
- uint32_t hartid_base;
- uint32_t num_sources;
- uint32_t num_priorities;
- uint32_t priority_base;
- uint32_t pending_base;
- uint32_t enable_base;
- uint32_t enable_stride;
- uint32_t context_base;
- uint32_t context_stride;
- uint32_t aperture_size;
-};
-
-DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
- uint32_t hartid_base, uint32_t num_sources,
- uint32_t num_priorities, uint32_t priority_base,
- uint32_t pending_base, uint32_t enable_base,
- uint32_t enable_stride, uint32_t context_base,
- uint32_t context_stride, uint32_t aperture_size);
-
-#endif
diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
index c2f3c8e129..60066375ab 100644
--- a/hw/misc/sifive_u_otp.c
+++ b/hw/misc/sifive_u_otp.c
@@ -19,11 +19,22 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "hw/misc/sifive_u_otp.h"
+#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
+
+#define WRITTEN_BIT_ON 0x1
+
+#define SET_FUSEARRAY_BIT(map, i, off, bit) \
+ map[i] = bit ? (map[i] | bit << off) : (map[i] & ~(0x1 << off))
+
+#define GET_FUSEARRAY_BIT(map, i, off) \
+ ((map[i] >> off) & 0x1)
static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
{
@@ -46,6 +57,16 @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
if ((s->pce & SIFIVE_U_OTP_PCE_EN) &&
(s->pdstb & SIFIVE_U_OTP_PDSTB_EN) &&
(s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) {
+
+ /* read from backend */
+ if (s->blk) {
+ int32_t buf;
+
+ blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf,
+ SIFIVE_U_OTP_FUSE_WORD);
+ return buf;
+ }
+
return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK];
} else {
return 0xff;
@@ -123,7 +144,30 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr,
s->ptrim = val32;
break;
case SIFIVE_U_OTP_PWE:
- s->pwe = val32;
+ s->pwe = val32 & SIFIVE_U_OTP_PWE_EN;
+
+ /* PWE is enabled. Ignore PAS=1 (no redundancy cell) */
+ if (s->pwe && !s->pas) {
+ if (GET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "write once error: idx<%u>, bit<%u>\n",
+ s->pa, s->paio);
+ break;
+ }
+
+ /* write bit data */
+ SET_FUSEARRAY_BIT(s->fuse, s->pa, s->paio, s->pdin);
+
+ /* write to backend */
+ if (s->blk) {
+ blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD,
+ &s->fuse[s->pa], SIFIVE_U_OTP_FUSE_WORD, 0);
+ }
+
+ /* update written bit */
+ SET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio, WRITTEN_BIT_ON);
+ }
+
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx
@@ -143,16 +187,48 @@ static const MemoryRegionOps sifive_u_otp_ops = {
static Property sifive_u_otp_properties[] = {
DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0),
+ DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk),
DEFINE_PROP_END_OF_LIST(),
};
static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
{
SiFiveUOTPState *s = SIFIVE_U_OTP(dev);
+ DriveInfo *dinfo;
memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s,
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
+
+ dinfo = drive_get_next(IF_NONE);
+ if (dinfo) {
+ int ret;
+ uint64_t perm;
+ int filesize;
+ BlockBackend *blk;
+
+ blk = blk_by_legacy_dinfo(dinfo);
+ filesize = SIFIVE_U_OTP_NUM_FUSES * SIFIVE_U_OTP_FUSE_WORD;
+ if (blk_getlength(blk) < filesize) {
+ error_setg(errp, "OTP drive size < 16K");
+ return;
+ }
+
+ qdev_prop_set_drive_err(dev, "drive", blk, errp);
+
+ if (s->blk) {
+ perm = BLK_PERM_CONSISTENT_READ |
+ (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE);
+ ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp);
+ if (ret < 0) {
+ return;
+ }
+
+ if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) {
+ error_setg(errp, "failed to read the initial flash content");
+ }
+ }
+ }
}
static void sifive_u_otp_reset(DeviceState *dev)
@@ -165,6 +241,23 @@ static void sifive_u_otp_reset(DeviceState *dev)
/* Make a valid content of serial number */
s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = s->serial;
s->fuse[SIFIVE_U_OTP_SERIAL_ADDR + 1] = ~(s->serial);
+
+ if (s->blk) {
+ /* Put serial number to backend as well*/
+ uint32_t serial_data;
+ int index = SIFIVE_U_OTP_SERIAL_ADDR;
+
+ serial_data = s->serial;
+ blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD,
+ &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0);
+
+ serial_data = ~(s->serial);
+ blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD,
+ &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0);
+ }
+
+ /* Initialize write-once map */
+ memset(s->fuse_wo, 0x00, sizeof(s->fuse_wo));
}
static void sifive_u_otp_class_init(ObjectClass *klass, void *data)
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 21adaae56e..9b3fe3fb1e 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -33,19 +33,36 @@
#include <libfdt.h>
#if defined(TARGET_RISCV32)
-# define KERNEL_BOOT_ADDRESS 0x80400000
#define fw_dynamic_info_data(__val) cpu_to_le32(__val)
#else
-# define KERNEL_BOOT_ADDRESS 0x80200000
#define fw_dynamic_info_data(__val) cpu_to_le64(__val)
#endif
-void riscv_find_and_load_firmware(MachineState *machine,
- const char *default_machine_firmware,
- hwaddr firmware_load_addr,
- symbol_fn_t sym_cb)
+bool riscv_is_32_bit(MachineState *machine)
+{
+ if (!strncmp(machine->cpu_type, "rv32", 4)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+target_ulong riscv_calc_kernel_start_addr(MachineState *machine,
+ target_ulong firmware_end_addr) {
+ if (riscv_is_32_bit(machine)) {
+ return QEMU_ALIGN_UP(firmware_end_addr, 4 * MiB);
+ } else {
+ return QEMU_ALIGN_UP(firmware_end_addr, 2 * MiB);
+ }
+}
+
+target_ulong riscv_find_and_load_firmware(MachineState *machine,
+ const char *default_machine_firmware,
+ hwaddr firmware_load_addr,
+ symbol_fn_t sym_cb)
{
char *firmware_filename = NULL;
+ target_ulong firmware_end_addr = firmware_load_addr;
if ((!machine->firmware) || (!strcmp(machine->firmware, "default"))) {
/*
@@ -60,9 +77,12 @@ void riscv_find_and_load_firmware(MachineState *machine,
if (firmware_filename) {
/* If not "none" load the firmware */
- riscv_load_firmware(firmware_filename, firmware_load_addr, sym_cb);
+ firmware_end_addr = riscv_load_firmware(firmware_filename,
+ firmware_load_addr, sym_cb);
g_free(firmware_filename);
}
+
+ return firmware_end_addr;
}
char *riscv_find_firmware(const char *firmware_filename)
@@ -91,24 +111,28 @@ target_ulong riscv_load_firmware(const char *firmware_filename,
hwaddr firmware_load_addr,
symbol_fn_t sym_cb)
{
- uint64_t firmware_entry;
+ uint64_t firmware_entry, firmware_size, firmware_end;
if (load_elf_ram_sym(firmware_filename, NULL, NULL, NULL,
- &firmware_entry, NULL, NULL, NULL,
+ &firmware_entry, NULL, &firmware_end, NULL,
0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) {
- return firmware_entry;
+ return firmware_end;
}
- if (load_image_targphys_as(firmware_filename, firmware_load_addr,
- ram_size, NULL) > 0) {
- return firmware_load_addr;
+ firmware_size = load_image_targphys_as(firmware_filename,
+ firmware_load_addr, ram_size, NULL);
+
+ if (firmware_size > 0) {
+ return firmware_load_addr + firmware_size;
}
error_report("could not load firmware '%s'", firmware_filename);
exit(1);
}
-target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb)
+target_ulong riscv_load_kernel(const char *kernel_filename,
+ target_ulong kernel_start_addr,
+ symbol_fn_t sym_cb)
{
uint64_t kernel_entry;
@@ -123,9 +147,9 @@ target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb)
return kernel_entry;
}
- if (load_image_targphys_as(kernel_filename, KERNEL_BOOT_ADDRESS,
+ if (load_image_targphys_as(kernel_filename, kernel_start_addr,
ram_size, NULL) > 0) {
- return KERNEL_BOOT_ADDRESS;
+ return kernel_start_addr;
}
error_report("could not load kernel '%s'", kernel_filename);
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index 0531bd879b..cc758b78b8 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -75,7 +75,8 @@ static void opentitan_board_init(MachineState *machine)
}
if (machine->kernel_filename) {
- riscv_load_kernel(machine->kernel_filename, NULL);
+ riscv_load_kernel(machine->kernel_filename,
+ memmap[IBEX_DEV_RAM].base, NULL);
}
}
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index fcfac16816..59bac4cc9a 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -114,7 +114,8 @@ static void sifive_e_machine_init(MachineState *machine)
memmap[SIFIVE_E_DEV_MROM].base, &address_space_memory);
if (machine->kernel_filename) {
- riscv_load_kernel(machine->kernel_filename, NULL);
+ riscv_load_kernel(machine->kernel_filename,
+ memmap[SIFIVE_E_DEV_DTIM].base, NULL);
}
}
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 6ad975d692..b2472c6627 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -415,6 +415,7 @@ static void sifive_u_machine_init(MachineState *machine)
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *flash0 = g_new(MemoryRegion, 1);
target_ulong start_addr = memmap[SIFIVE_U_DEV_DRAM].base;
+ target_ulong firmware_end_addr, kernel_start_addr;
uint32_t start_addr_hi32 = 0x00000000;
int i;
uint32_t fdt_load_addr;
@@ -424,6 +425,8 @@ static void sifive_u_machine_init(MachineState *machine)
object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_U_SOC);
object_property_set_uint(OBJECT(&s->soc), "serial", s->serial,
&error_abort);
+ object_property_set_str(OBJECT(&s->soc), "cpu-type", machine->cpu_type,
+ &error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
/* register RAM */
@@ -472,10 +475,15 @@ static void sifive_u_machine_init(MachineState *machine)
break;
}
- riscv_find_and_load_firmware(machine, BIOS_FILENAME, start_addr, NULL);
+ firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
+ start_addr, NULL);
if (machine->kernel_filename) {
- kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL);
+ kernel_start_addr = riscv_calc_kernel_start_addr(machine,
+ firmware_end_addr);
+
+ kernel_entry = riscv_load_kernel(machine->kernel_filename,
+ kernel_start_addr, NULL);
if (machine->initrd_filename) {
hwaddr start;
@@ -590,6 +598,11 @@ static void sifive_u_machine_class_init(ObjectClass *oc, void *data)
mc->init = sifive_u_machine_init;
mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT;
mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1;
+#if defined(TARGET_RISCV32)
+ mc->default_cpu_type = TYPE_RISCV_CPU_SIFIVE_U34;
+#elif defined(TARGET_RISCV64)
+ mc->default_cpu_type = TYPE_RISCV_CPU_SIFIVE_U54;
+#endif
mc->default_cpus = mc->min_cpus;
object_class_property_add_bool(oc, "start-in-flash",
@@ -618,7 +631,6 @@ type_init(sifive_u_machine_init_register_types)
static void sifive_u_soc_instance_init(Object *obj)
{
- MachineState *ms = MACHINE(qdev_get_machine());
SiFiveUSoCState *s = RISCV_U_SOC(obj);
object_initialize_child(obj, "e-cluster", &s->e_cluster, TYPE_CPU_CLUSTER);
@@ -636,10 +648,6 @@ static void sifive_u_soc_instance_init(Object *obj)
object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", &s->u_cpus,
TYPE_RISCV_HART_ARRAY);
- qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1);
- qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1);
- qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", SIFIVE_U_CPU);
- qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", 0x1004);
object_initialize_child(obj, "prci", &s->prci, TYPE_SIFIVE_U_PRCI);
object_initialize_child(obj, "otp", &s->otp, TYPE_SIFIVE_U_OTP);
@@ -661,6 +669,11 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
int i;
NICInfo *nd = &nd_table[0];
+ qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1);
+ qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1);
+ qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", s->cpu_type);
+ qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", 0x1004);
+
sysbus_realize(SYS_BUS_DEVICE(&s->e_cpus), &error_abort);
sysbus_realize(SYS_BUS_DEVICE(&s->u_cpus), &error_abort);
/*
@@ -792,6 +805,7 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
static Property sifive_u_soc_props[] = {
DEFINE_PROP_UINT32("serial", SiFiveUSoCState, serial, OTP_SERIAL),
+ DEFINE_PROP_STRING("cpu-type", SiFiveUSoCState, cpu_type),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 3fd152a035..facac6e7d2 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -195,6 +195,7 @@ static void spike_board_init(MachineState *machine)
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
+ target_ulong firmware_end_addr, kernel_start_addr;
uint32_t fdt_load_addr;
uint64_t kernel_entry;
char *soc_name;
@@ -261,12 +262,16 @@ static void spike_board_init(MachineState *machine)
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
mask_rom);
- riscv_find_and_load_firmware(machine, BIOS_FILENAME,
- memmap[SPIKE_DRAM].base,
- htif_symbol_callback);
+ firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
+ memmap[SPIKE_DRAM].base,
+ htif_symbol_callback);
if (machine->kernel_filename) {
+ kernel_start_addr = riscv_calc_kernel_start_addr(machine,
+ firmware_end_addr);
+
kernel_entry = riscv_load_kernel(machine->kernel_filename,
+ kernel_start_addr,
htif_symbol_callback);
if (machine->initrd_filename) {
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 41bd2f38ba..6bfd10dfc7 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -493,6 +493,7 @@ static void virt_machine_init(MachineState *machine)
char *plic_hart_config, *soc_name;
size_t plic_hart_config_len;
target_ulong start_addr = memmap[VIRT_DRAM].base;
+ target_ulong firmware_end_addr, kernel_start_addr;
uint32_t fdt_load_addr;
uint64_t kernel_entry;
DeviceState *mmio_plic, *virtio_plic, *pcie_plic;
@@ -602,11 +603,15 @@ static void virt_machine_init(MachineState *machine)
memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
mask_rom);
- riscv_find_and_load_firmware(machine, BIOS_FILENAME,
- memmap[VIRT_DRAM].base, NULL);
+ firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
+ start_addr, NULL);
if (machine->kernel_filename) {
- kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL);
+ kernel_start_addr = riscv_calc_kernel_start_addr(machine,
+ firmware_end_addr);
+
+ kernel_entry = riscv_load_kernel(machine->kernel_filename,
+ kernel_start_addr, NULL);
if (machine->initrd_filename) {
hwaddr start;