aboutsummaryrefslogtreecommitdiff
path: root/hw/riscv
diff options
context:
space:
mode:
Diffstat (limited to 'hw/riscv')
-rw-r--r--hw/riscv/boot.c35
-rw-r--r--hw/riscv/microchip_pfsoc.c3
-rw-r--r--hw/riscv/sifive_u.c3
-rw-r--r--hw/riscv/spike.c3
-rw-r--r--hw/riscv/virt.c3
5 files changed, 31 insertions, 16 deletions
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 2e53494b08..c7e0e50bd8 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -250,34 +250,45 @@ void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
}
/*
- * The FDT should be put at the farthest point possible to
- * avoid overwriting it with the kernel/initrd.
+ * This function makes an assumption that the DRAM interval
+ * 'dram_base' + 'dram_size' is contiguous.
*
- * This function makes an assumption that the DRAM is
- * contiguous. It also cares about 32-bit systems and
- * will limit fdt_addr to be addressable by them even for
- * 64-bit CPUs.
+ * Considering that 'dram_end' is the lowest value between
+ * the end of the DRAM block and MachineState->ram_size, the
+ * FDT location will vary according to 'dram_base':
+ *
+ * - if 'dram_base' is less that 3072 MiB, the FDT will be
+ * put at the lowest value between 3072 MiB and 'dram_end';
+ *
+ * - if 'dram_base' is higher than 3072 MiB, the FDT will be
+ * put at 'dram_end'.
*
* The FDT is fdt_packed() during the calculation.
*/
-uint64_t riscv_compute_fdt_addr(hwaddr dram_base, uint64_t mem_size,
- void *fdt)
+uint64_t riscv_compute_fdt_addr(hwaddr dram_base, hwaddr dram_size,
+ MachineState *ms)
{
- uint64_t temp;
- hwaddr dram_end = dram_base + mem_size;
- int ret = fdt_pack(fdt);
+ int ret = fdt_pack(ms->fdt);
+ hwaddr dram_end, temp;
int fdtsize;
/* Should only fail if we've built a corrupted tree */
g_assert(ret == 0);
- fdtsize = fdt_totalsize(fdt);
+ fdtsize = fdt_totalsize(ms->fdt);
if (fdtsize <= 0) {
error_report("invalid device-tree");
exit(1);
}
/*
+ * A dram_size == 0, usually from a MemMapEntry[].size element,
+ * means that the DRAM block goes all the way to ms->ram_size.
+ */
+ dram_end = dram_base;
+ dram_end += dram_size ? MIN(ms->ram_size, dram_size) : ms->ram_size;
+
+ /*
* We should put fdt as far as possible to avoid kernel/initrd overwriting
* its content. But it should be addressable by 32 bit system as well.
* Thus, put it at an 2MB aligned address that less than fdt size from the
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index 17499d4152..2b91e49561 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -642,7 +642,8 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
/* Compute the fdt load address in dram */
fdt_load_addr = riscv_compute_fdt_addr(memmap[MICROCHIP_PFSOC_DRAM_LO].base,
- machine->ram_size, machine->fdt);
+ memmap[MICROCHIP_PFSOC_DRAM_LO].size,
+ machine);
riscv_load_fdt(fdt_load_addr, machine->fdt);
/* Load the reset vector */
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 626d4dc2f3..d3ab7a9cda 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -617,7 +617,8 @@ static void sifive_u_machine_init(MachineState *machine)
}
fdt_load_addr = riscv_compute_fdt_addr(memmap[SIFIVE_U_DEV_DRAM].base,
- machine->ram_size, machine->fdt);
+ memmap[SIFIVE_U_DEV_DRAM].size,
+ machine);
riscv_load_fdt(fdt_load_addr, machine->fdt);
if (!riscv_is_32bit(&s->soc.u_cpus)) {
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index f1114f2c71..cc3f6dac17 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -325,7 +325,8 @@ static void spike_board_init(MachineState *machine)
}
fdt_load_addr = riscv_compute_fdt_addr(memmap[SPIKE_DRAM].base,
- machine->ram_size, machine->fdt);
+ memmap[SPIKE_DRAM].size,
+ machine);
riscv_load_fdt(fdt_load_addr, machine->fdt);
/* load the reset vector */
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 2e0a0cdb17..a061151a6f 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1304,7 +1304,8 @@ static void virt_machine_done(Notifier *notifier, void *data)
}
fdt_load_addr = riscv_compute_fdt_addr(memmap[VIRT_DRAM].base,
- machine->ram_size, machine->fdt);
+ memmap[VIRT_DRAM].size,
+ machine);
riscv_load_fdt(fdt_load_addr, machine->fdt);
/* load the reset vector */