hw/riscv: Add the checking if DTB overlaps to kernel or initrd

DTB is placed to the end of memory, so we will check if the start
address of DTB overlaps to the address of kernel/initrd.

Signed-off-by: Jim Shu <jim.shu@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Message-ID: <20241120153935.24706-4-jim.shu@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Jim Shu 2024-11-20 23:39:35 +08:00 committed by Alistair Francis
parent d3592955af
commit 1a65064c1f
2 changed files with 27 additions and 1 deletions

View file

@ -70,6 +70,7 @@ char *riscv_plic_hart_config_string(int hart_count)
void riscv_boot_info_init(RISCVBootInfo *info, RISCVHartArrayState *harts) void riscv_boot_info_init(RISCVBootInfo *info, RISCVHartArrayState *harts)
{ {
info->kernel_size = 0; info->kernel_size = 0;
info->initrd_size = 0;
info->is_32bit = riscv_is_32bit(harts); info->is_32bit = riscv_is_32bit(harts);
} }
@ -213,6 +214,9 @@ static void riscv_load_initrd(MachineState *machine, RISCVBootInfo *info)
} }
} }
info->initrd_start = start;
info->initrd_size = size;
/* Some RISC-V machines (e.g. opentitan) don't have a fdt. */ /* Some RISC-V machines (e.g. opentitan) don't have a fdt. */
if (fdt) { if (fdt) {
end = start + size; end = start + size;
@ -309,6 +313,7 @@ uint64_t riscv_compute_fdt_addr(hwaddr dram_base, hwaddr dram_size,
int ret = fdt_pack(ms->fdt); int ret = fdt_pack(ms->fdt);
hwaddr dram_end, temp; hwaddr dram_end, temp;
int fdtsize; int fdtsize;
uint64_t dtb_start, dtb_start_limit;
/* Should only fail if we've built a corrupted tree */ /* Should only fail if we've built a corrupted tree */
g_assert(ret == 0); g_assert(ret == 0);
@ -319,6 +324,17 @@ uint64_t riscv_compute_fdt_addr(hwaddr dram_base, hwaddr dram_size,
exit(1); exit(1);
} }
if (info->initrd_size) {
/* If initrd is successfully loaded, place DTB after it. */
dtb_start_limit = info->initrd_start + info->initrd_size;
} else if (info->kernel_size) {
/* If only kernel is successfully loaded, place DTB after it. */
dtb_start_limit = info->image_high_addr;
} else {
/* Otherwise, do not check DTB overlapping */
dtb_start_limit = 0;
}
/* /*
* A dram_size == 0, usually from a MemMapEntry[].size element, * A dram_size == 0, usually from a MemMapEntry[].size element,
* means that the DRAM block goes all the way to ms->ram_size. * means that the DRAM block goes all the way to ms->ram_size.
@ -338,7 +354,14 @@ uint64_t riscv_compute_fdt_addr(hwaddr dram_base, hwaddr dram_size,
temp = (dram_base < 3072 * MiB) ? MIN(dram_end, 3072 * MiB) : dram_end; temp = (dram_base < 3072 * MiB) ? MIN(dram_end, 3072 * MiB) : dram_end;
} }
return QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB); dtb_start = QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB);
if (dtb_start_limit && (dtb_start < dtb_start_limit)) {
error_report("No enough memory to place DTB after kernel/initrd");
exit(1);
}
return dtb_start;
} }
/* /*

View file

@ -32,6 +32,9 @@ typedef struct RISCVBootInfo {
hwaddr image_low_addr; hwaddr image_low_addr;
hwaddr image_high_addr; hwaddr image_high_addr;
hwaddr initrd_start;
ssize_t initrd_size;
bool is_32bit; bool is_32bit;
} RISCVBootInfo; } RISCVBootInfo;