From: Jim Shu Date: Wed, 20 Nov 2024 15:39:35 +0000 (+0800) Subject: hw/riscv: Add the checking if DTB overlaps to kernel or initrd X-Git-Tag: v10.0.0-rc0~110^2~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1a65064c1f4dc701370c1d59ac1b85afa198b3b0;p=thirdparty%2Fqemu.git 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 Reviewed-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20241120153935.24706-4-jim.shu@sifive.com> Signed-off-by: Alistair Francis --- diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 81d27f935e5..bc8074fec88 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -70,6 +70,7 @@ char *riscv_plic_hart_config_string(int hart_count) void riscv_boot_info_init(RISCVBootInfo *info, RISCVHartArrayState *harts) { info->kernel_size = 0; + info->initrd_size = 0; 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. */ if (fdt) { 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); hwaddr dram_end, temp; int fdtsize; + uint64_t dtb_start, dtb_start_limit; /* Should only fail if we've built a corrupted tree */ g_assert(ret == 0); @@ -319,6 +324,17 @@ uint64_t riscv_compute_fdt_addr(hwaddr dram_base, hwaddr dram_size, 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, * 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; } - 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; } /* diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index 06b51ed086a..7d59b2e6c63 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -32,6 +32,9 @@ typedef struct RISCVBootInfo { hwaddr image_low_addr; hwaddr image_high_addr; + hwaddr initrd_start; + ssize_t initrd_size; + bool is_32bit; } RISCVBootInfo;