aboutsummaryrefslogtreecommitdiff
path: root/hw/riscv
diff options
context:
space:
mode:
authorDaniel Henrique Barboza <dbarboza@ventanamicro.com>2023-02-01 14:12:11 -0300
committerAlistair Francis <alistair.francis@wdc.com>2023-02-07 08:19:23 +1000
commitbc2c01535317ebfd994668bb04a040c452247be3 (patch)
treea9310add35640cf01807e445781307d95291fc32 /hw/riscv
parent909f7da60472b82668d2b2abdb19eba53603b408 (diff)
downloadqemu-bc2c01535317ebfd994668bb04a040c452247be3.zip
qemu-bc2c01535317ebfd994668bb04a040c452247be3.tar.gz
qemu-bc2c01535317ebfd994668bb04a040c452247be3.tar.bz2
hw/riscv: split fdt address calculation from fdt load
A common trend in other archs is to calculate the fdt address, which is usually straightforward, and then calling a function that loads the fdt/dtb by using that address. riscv_load_fdt() is doing a bit too much in comparison. It's calculating the fdt address via an elaborated heuristic to put the FDT at the bottom of DRAM, and "bottom of DRAM" will vary across boards and configurations, then it's actually loading the fdt, and finally it's returning the fdt address used to the caller. Reduce the existing complexity of riscv_load_fdt() by splitting its code into a new function, riscv_compute_fdt_addr(), that will take care of all fdt address logic. riscv_load_fdt() can then be a simple function that just loads a fdt at the given fdt address. We're also taken the opportunity to clarify the intentions and assumptions made by these functions. riscv_load_fdt() is now receiving a hwaddr as fdt_addr because there is no restriction of having to load the fdt in higher addresses that doesn't fit in an uint32_t. Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-Id: <20230201171212.1219375-3-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'hw/riscv')
-rw-r--r--hw/riscv/boot.c30
-rw-r--r--hw/riscv/microchip_pfsoc.c6
-rw-r--r--hw/riscv/sifive_u.c7
-rw-r--r--hw/riscv/spike.c6
-rw-r--r--hw/riscv/virt.c7
5 files changed, 40 insertions, 16 deletions
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 2d03a9a..2e53494 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -249,9 +249,21 @@ void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
}
}
-uint64_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt)
+/*
+ * 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 is
+ * contiguous. It also cares about 32-bit systems and
+ * will limit fdt_addr to be addressable by them even for
+ * 64-bit CPUs.
+ *
+ * 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 temp, fdt_addr;
+ uint64_t temp;
hwaddr dram_end = dram_base + mem_size;
int ret = fdt_pack(fdt);
int fdtsize;
@@ -272,7 +284,17 @@ uint64_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt)
* end of dram or 3GB whichever is lesser.
*/
temp = (dram_base < 3072 * MiB) ? MIN(dram_end, 3072 * MiB) : dram_end;
- fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB);
+
+ return QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB);
+}
+
+/*
+ * 'fdt_addr' is received as hwaddr because boards might put
+ * the FDT beyond 32-bit addressing boundary.
+ */
+void riscv_load_fdt(hwaddr fdt_addr, void *fdt)
+{
+ uint32_t fdtsize = fdt_totalsize(fdt);
/* copy in the device tree */
qemu_fdt_dumpdtb(fdt, fdtsize);
@@ -281,8 +303,6 @@ uint64_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt)
&address_space_memory);
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
rom_ptr_for_as(&address_space_memory, fdt_addr, fdtsize));
-
- return fdt_addr;
}
void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index 82ae5e7..17499d4 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -641,8 +641,10 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
}
/* Compute the fdt load address in dram */
- fdt_load_addr = riscv_load_fdt(memmap[MICROCHIP_PFSOC_DRAM_LO].base,
- machine->ram_size, machine->fdt);
+ fdt_load_addr = riscv_compute_fdt_addr(memmap[MICROCHIP_PFSOC_DRAM_LO].base,
+ machine->ram_size, machine->fdt);
+ riscv_load_fdt(fdt_load_addr, machine->fdt);
+
/* Load the reset vector */
riscv_setup_rom_reset_vec(machine, &s->soc.u_cpus, firmware_load_addr,
memmap[MICROCHIP_PFSOC_ENVM_DATA].base,
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 2fb6ee2..626d4dc 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -616,9 +616,10 @@ static void sifive_u_machine_init(MachineState *machine)
kernel_entry = 0;
}
- /* Compute the fdt load address in dram */
- fdt_load_addr = riscv_load_fdt(memmap[SIFIVE_U_DEV_DRAM].base,
- machine->ram_size, machine->fdt);
+ fdt_load_addr = riscv_compute_fdt_addr(memmap[SIFIVE_U_DEV_DRAM].base,
+ machine->ram_size, machine->fdt);
+ riscv_load_fdt(fdt_load_addr, machine->fdt);
+
if (!riscv_is_32bit(&s->soc.u_cpus)) {
start_addr_hi32 = (uint64_t)start_addr >> 32;
}
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 04d2362..f1114f2 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -324,9 +324,9 @@ static void spike_board_init(MachineState *machine)
kernel_entry = 0;
}
- /* Compute the fdt load address in dram */
- fdt_load_addr = riscv_load_fdt(memmap[SPIKE_DRAM].base,
- machine->ram_size, machine->fdt);
+ fdt_load_addr = riscv_compute_fdt_addr(memmap[SPIKE_DRAM].base,
+ machine->ram_size, machine->fdt);
+ riscv_load_fdt(fdt_load_addr, machine->fdt);
/* load the reset vector */
riscv_setup_rom_reset_vec(machine, &s->soc[0], memmap[SPIKE_DRAM].base,
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index e420254..2e0a0cd 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1303,9 +1303,10 @@ static void virt_machine_done(Notifier *notifier, void *data)
start_addr = virt_memmap[VIRT_FLASH].base;
}
- /* Compute the fdt load address in dram */
- fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
- machine->ram_size, machine->fdt);
+ fdt_load_addr = riscv_compute_fdt_addr(memmap[VIRT_DRAM].base,
+ machine->ram_size, machine->fdt);
+ riscv_load_fdt(fdt_load_addr, machine->fdt);
+
/* load the reset vector */
riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr,
virt_memmap[VIRT_MROM].base,