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>
---
hw/riscv/boot.c | 25 ++++++++++++++++++++++++-
include/hw/riscv/boot.h | 3 +++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 81d27f935e..bc8074fec8 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 06b51ed086..7d59b2e6c6 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;
--
2.17.1
On Thu, Nov 21, 2024 at 12:42 AM Jim Shu <jim.shu@sifive.com> wrote:
>
> 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>
Alistair
> ---
> hw/riscv/boot.c | 25 ++++++++++++++++++++++++-
> include/hw/riscv/boot.h | 3 +++
> 2 files changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> index 81d27f935e..bc8074fec8 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 06b51ed086..7d59b2e6c6 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;
>
> --
> 2.17.1
>
>
On 11/20/24 12:39 PM, Jim Shu wrote:
> 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: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> hw/riscv/boot.c | 25 ++++++++++++++++++++++++-
> include/hw/riscv/boot.h | 3 +++
> 2 files changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> index 81d27f935e..bc8074fec8 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 06b51ed086..7d59b2e6c6 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;
>
© 2016 - 2026 Red Hat, Inc.