[PATCH 2/4] hw/riscv/boot: Account for discontiguous memory when loading firmware

Joel Stanley posted 4 patches 1 month ago
Maintainers: Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Weiwei Li <liwei1518@gmail.com>, Daniel Henrique Barboza <dbarboza@ventanamicro.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>, Vijai Kumar K <vijai@behindbytes.com>, Ran Wang <wangran@bosc.ac.cn>
[PATCH 2/4] hw/riscv/boot: Account for discontiguous memory when loading firmware
Posted by Joel Stanley 1 month ago
From: Nicholas Piggin <npiggin@gmail.com>

This loads firmware into the first (low) memory range,
accounting for machines having discontiguous memory regions.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
 include/hw/riscv/boot.h    |  5 ++++-
 hw/riscv/boot.c            | 18 ++++++++++++------
 hw/riscv/microchip_pfsoc.c |  6 ++++--
 hw/riscv/opentitan.c       |  6 ++++--
 hw/riscv/shakti_c.c        |  6 +++++-
 hw/riscv/sifive_u.c        |  3 ++-
 hw/riscv/spike.c           |  6 ++++--
 hw/riscv/virt.c            |  7 ++++---
 hw/riscv/xiangshan_kmh.c   |  6 +++++-
 9 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index 115e3222174f..fb90bf12399e 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -53,13 +53,16 @@ void riscv_boot_info_init_discontig_mem(RISCVBootInfo *info,
 vaddr riscv_calc_kernel_start_addr(RISCVBootInfo *info,
                                    hwaddr firmware_end_addr);
 hwaddr riscv_find_and_load_firmware(MachineState *machine,
+                                    RISCVBootInfo *info,
                                     const char *default_machine_firmware,
                                     hwaddr *firmware_load_addr,
                                     symbol_fn_t sym_cb);
 const char *riscv_default_firmware_name(RISCVHartArrayState *harts);
 char *riscv_find_firmware(const char *firmware_filename,
                           const char *default_machine_firmware);
-hwaddr riscv_load_firmware(const char *firmware_filename,
+hwaddr riscv_load_firmware(MachineState *machine,
+                           RISCVBootInfo *info,
+                           const char *firmware_filename,
                            hwaddr *firmware_load_addr,
                            symbol_fn_t sym_cb);
 void riscv_load_kernel(MachineState *machine,
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 9babb85b0458..f3857e984240 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -145,6 +145,7 @@ char *riscv_find_firmware(const char *firmware_filename,
 }
 
 hwaddr riscv_find_and_load_firmware(MachineState *machine,
+                                    RISCVBootInfo *info,
                                     const char *default_machine_firmware,
                                     hwaddr *firmware_load_addr,
                                     symbol_fn_t sym_cb)
@@ -157,7 +158,8 @@ hwaddr riscv_find_and_load_firmware(MachineState *machine,
 
     if (firmware_filename) {
         /* If not "none" load the firmware */
-        firmware_end_addr = riscv_load_firmware(firmware_filename,
+        firmware_end_addr = riscv_load_firmware(machine, info,
+                                                firmware_filename,
                                                 firmware_load_addr, sym_cb);
         g_free(firmware_filename);
     }
@@ -165,10 +167,13 @@ hwaddr riscv_find_and_load_firmware(MachineState *machine,
     return firmware_end_addr;
 }
 
-hwaddr riscv_load_firmware(const char *firmware_filename,
+hwaddr riscv_load_firmware(MachineState *machine,
+                           RISCVBootInfo *info,
+                           const char *firmware_filename,
                            hwaddr *firmware_load_addr,
                            symbol_fn_t sym_cb)
 {
+    uint64_t mem_size = info->ram_low_size ?: machine->ram_size;
     uint64_t firmware_entry, firmware_end;
     ssize_t firmware_size;
 
@@ -183,7 +188,7 @@ hwaddr riscv_load_firmware(const char *firmware_filename,
 
     firmware_size = load_image_targphys_as(firmware_filename,
                                            *firmware_load_addr,
-                                           current_machine->ram_size, NULL,
+                                           mem_size, NULL,
                                            NULL);
 
     if (firmware_size > 0) {
@@ -197,7 +202,7 @@ hwaddr riscv_load_firmware(const char *firmware_filename,
 static void riscv_load_initrd(MachineState *machine, RISCVBootInfo *info)
 {
     const char *filename = machine->initrd_filename;
-    uint64_t mem_size = machine->ram_size;
+    uint64_t mem_size = info->ram_low_size ?: machine->ram_size;
     void *fdt = machine->fdt;
     hwaddr start, end;
     ssize_t size;
@@ -243,6 +248,7 @@ void riscv_load_kernel(MachineState *machine,
                        bool load_initrd,
                        symbol_fn_t sym_cb)
 {
+    uint64_t mem_size = info->ram_low_size ?: machine->ram_size;
     const char *kernel_filename = machine->kernel_filename;
     ssize_t kernel_size;
     void *fdt = machine->fdt;
@@ -274,7 +280,7 @@ void riscv_load_kernel(MachineState *machine,
     }
 
     kernel_size = load_image_targphys_as(kernel_filename, kernel_start_addr,
-                                         current_machine->ram_size, NULL, NULL);
+                                         mem_size, NULL, NULL);
     if (kernel_size > 0) {
         info->kernel_size = kernel_size;
         info->image_low_addr = kernel_start_addr;
@@ -370,7 +376,7 @@ uint64_t riscv_compute_fdt_addr(hwaddr dram_base, hwaddr dram_size,
     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");
+        error_report("Not enough memory to place DTB after kernel/initrd");
         exit(1);
     }
 
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index 4ff83e494034..8905ed0ba190 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -615,18 +615,20 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
         firmware_load_addr = RESET_VECTOR;
     }
 
+    riscv_boot_info_init(&boot_info, &s->soc.u_cpus);
+
     /* Load the firmware if necessary */
     firmware_end_addr = firmware_load_addr;
     if (firmware_name) {
         char *filename = riscv_find_firmware(firmware_name, NULL);
         if (filename) {
-            firmware_end_addr = riscv_load_firmware(filename,
+            firmware_end_addr = riscv_load_firmware(machine, &boot_info,
+                                                    filename,
                                                     &firmware_load_addr, NULL);
             g_free(filename);
         }
     }
 
-    riscv_boot_info_init(&boot_info, &s->soc.u_cpus);
     if (machine->kernel_filename) {
         kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info,
                                                          firmware_end_addr);
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index 309125e854bc..8cd660dd4154 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -99,12 +99,14 @@ static void opentitan_machine_init(MachineState *machine)
     memory_region_add_subregion(sys_mem,
         memmap[IBEX_DEV_RAM].base, machine->ram);
 
+    riscv_boot_info_init(&boot_info, &s->soc.cpus);
+
     if (machine->firmware) {
         hwaddr firmware_load_addr = memmap[IBEX_DEV_RAM].base;
-        riscv_load_firmware(machine->firmware, &firmware_load_addr, NULL);
+        riscv_load_firmware(machine, &boot_info, machine->firmware,
+                            &firmware_load_addr, NULL);
     }
 
-    riscv_boot_info_init(&boot_info, &s->soc.cpus);
     if (machine->kernel_filename) {
         riscv_load_kernel(machine, &boot_info,
                           memmap[IBEX_DEV_RAM].base,
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
index 49a39b30212d..eb720d9cdf5d 100644
--- a/hw/riscv/shakti_c.c
+++ b/hw/riscv/shakti_c.c
@@ -45,6 +45,7 @@ static void shakti_c_machine_state_init(MachineState *mstate)
 {
     ShaktiCMachineState *sms = RISCV_SHAKTI_MACHINE(mstate);
     MemoryRegion *system_memory = get_system_memory();
+    RISCVBootInfo boot_info;
     hwaddr firmware_load_addr = shakti_c_memmap[SHAKTI_C_RAM].base;
 
     /* Initialize SoC */
@@ -57,8 +58,11 @@ static void shakti_c_machine_state_init(MachineState *mstate)
                                 shakti_c_memmap[SHAKTI_C_RAM].base,
                                 mstate->ram);
 
+    riscv_boot_info_init(&boot_info, &sms->soc.cpus);
+
     if (mstate->firmware) {
-        riscv_load_firmware(mstate->firmware, &firmware_load_addr, NULL);
+        riscv_load_firmware(mstate, &boot_info, mstate->firmware,
+                            &firmware_load_addr, NULL);
     }
 
     /* ROM reset vector */
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 7ec67b256514..4c526f73edf6 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -590,7 +590,8 @@ static void sifive_u_machine_init(MachineState *machine)
     }
 
     firmware_name = riscv_default_firmware_name(&s->soc.u_cpus);
-    firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
+    firmware_end_addr = riscv_find_and_load_firmware(machine, &boot_info,
+                                                     firmware_name,
                                                      &start_addr, NULL);
 
     riscv_boot_info_init(&boot_info, &s->soc.u_cpus);
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 1493b928dad3..86b06a173565 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -289,9 +289,12 @@ static void spike_board_init(MachineState *machine)
         }
     }
 
+    riscv_boot_info_init(&boot_info, &s->soc[0]);
+
     /* Load firmware */
     if (firmware_name) {
-        firmware_end_addr = riscv_load_firmware(firmware_name,
+        firmware_end_addr = riscv_load_firmware(machine, &boot_info,
+                                                firmware_name,
                                                 &firmware_load_addr,
                                                 htif_symbol_callback);
         g_free(firmware_name);
@@ -301,7 +304,6 @@ static void spike_board_init(MachineState *machine)
     create_fdt(s, memmap, riscv_is_32bit(&s->soc[0]), htif_custom_base);
 
     /* Load kernel */
-    riscv_boot_info_init(&boot_info, &s->soc[0]);
     if (machine->kernel_filename) {
         kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info,
                                                          firmware_end_addr);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index bd8608ea5bfd..a907ca359e09 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1466,7 +1466,10 @@ static void virt_machine_done(Notifier *notifier, void *data)
         }
     }
 
-    firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
+    riscv_boot_info_init(&boot_info, &s->soc[0]);
+
+    firmware_end_addr = riscv_find_and_load_firmware(machine, &boot_info,
+                                                     firmware_name,
                                                      &start_addr, NULL);
 
     pflash_blk0 = pflash_cfi01_get_blk(s->flash[0]);
@@ -1489,8 +1492,6 @@ static void virt_machine_done(Notifier *notifier, void *data)
         }
     }
 
-    riscv_boot_info_init(&boot_info, &s->soc[0]);
-
     if (machine->kernel_filename && !kernel_entry) {
         kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info,
                                                          firmware_end_addr);
diff --git a/hw/riscv/xiangshan_kmh.c b/hw/riscv/xiangshan_kmh.c
index 436e51c1c593..247a0b5d1f21 100644
--- a/hw/riscv/xiangshan_kmh.c
+++ b/hw/riscv/xiangshan_kmh.c
@@ -166,6 +166,7 @@ static void xiangshan_kmh_machine_init(MachineState *machine)
     const MemMapEntry *memmap = xiangshan_kmh_memmap;
     MemoryRegion *system_memory = get_system_memory();
     hwaddr start_addr = memmap[XIANGSHAN_KMH_DRAM].base;
+    RISCVBootInfo boot_info;
 
     /* Initialize SoC */
     object_initialize_child(OBJECT(machine), "soc", &s->soc,
@@ -177,13 +178,16 @@ static void xiangshan_kmh_machine_init(MachineState *machine)
                                 memmap[XIANGSHAN_KMH_DRAM].base,
                                 machine->ram);
 
+    riscv_boot_info_init(&boot_info, &s->soc.cpus);
+
     /* ROM reset vector */
     riscv_setup_rom_reset_vec(machine, &s->soc.cpus,
                               start_addr,
                               memmap[XIANGSHAN_KMH_ROM].base,
                               memmap[XIANGSHAN_KMH_ROM].size, 0, 0);
     if (machine->firmware) {
-        riscv_load_firmware(machine->firmware, &start_addr, NULL);
+        riscv_load_firmware(machine, &boot_info, machine->firmware,
+                            &start_addr, NULL);
     }
 
     /* Note: dtb has been integrated into firmware(OpenSBI) when compiling */
-- 
2.47.3
Re: [PATCH 2/4] hw/riscv/boot: Account for discontiguous memory when loading firmware
Posted by Daniel Henrique Barboza 3 weeks, 4 days ago

On 1/9/2026 10:16 AM, Joel Stanley wrote:
> From: Nicholas Piggin <npiggin@gmail.com>
> 
> This loads firmware into the first (low) memory range,
> accounting for machines having discontiguous memory regions.
> 
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---

Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>

>   include/hw/riscv/boot.h    |  5 ++++-
>   hw/riscv/boot.c            | 18 ++++++++++++------
>   hw/riscv/microchip_pfsoc.c |  6 ++++--
>   hw/riscv/opentitan.c       |  6 ++++--
>   hw/riscv/shakti_c.c        |  6 +++++-
>   hw/riscv/sifive_u.c        |  3 ++-
>   hw/riscv/spike.c           |  6 ++++--
>   hw/riscv/virt.c            |  7 ++++---
>   hw/riscv/xiangshan_kmh.c   |  6 +++++-
>   9 files changed, 44 insertions(+), 19 deletions(-)
> 
> diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
> index 115e3222174f..fb90bf12399e 100644
> --- a/include/hw/riscv/boot.h
> +++ b/include/hw/riscv/boot.h
> @@ -53,13 +53,16 @@ void riscv_boot_info_init_discontig_mem(RISCVBootInfo *info,
>   vaddr riscv_calc_kernel_start_addr(RISCVBootInfo *info,
>                                      hwaddr firmware_end_addr);
>   hwaddr riscv_find_and_load_firmware(MachineState *machine,
> +                                    RISCVBootInfo *info,
>                                       const char *default_machine_firmware,
>                                       hwaddr *firmware_load_addr,
>                                       symbol_fn_t sym_cb);
>   const char *riscv_default_firmware_name(RISCVHartArrayState *harts);
>   char *riscv_find_firmware(const char *firmware_filename,
>                             const char *default_machine_firmware);
> -hwaddr riscv_load_firmware(const char *firmware_filename,
> +hwaddr riscv_load_firmware(MachineState *machine,
> +                           RISCVBootInfo *info,
> +                           const char *firmware_filename,
>                              hwaddr *firmware_load_addr,
>                              symbol_fn_t sym_cb);
>   void riscv_load_kernel(MachineState *machine,
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> index 9babb85b0458..f3857e984240 100644
> --- a/hw/riscv/boot.c
> +++ b/hw/riscv/boot.c
> @@ -145,6 +145,7 @@ char *riscv_find_firmware(const char *firmware_filename,
>   }
>   
>   hwaddr riscv_find_and_load_firmware(MachineState *machine,
> +                                    RISCVBootInfo *info,
>                                       const char *default_machine_firmware,
>                                       hwaddr *firmware_load_addr,
>                                       symbol_fn_t sym_cb)
> @@ -157,7 +158,8 @@ hwaddr riscv_find_and_load_firmware(MachineState *machine,
>   
>       if (firmware_filename) {
>           /* If not "none" load the firmware */
> -        firmware_end_addr = riscv_load_firmware(firmware_filename,
> +        firmware_end_addr = riscv_load_firmware(machine, info,
> +                                                firmware_filename,
>                                                   firmware_load_addr, sym_cb);
>           g_free(firmware_filename);
>       }
> @@ -165,10 +167,13 @@ hwaddr riscv_find_and_load_firmware(MachineState *machine,
>       return firmware_end_addr;
>   }
>   
> -hwaddr riscv_load_firmware(const char *firmware_filename,
> +hwaddr riscv_load_firmware(MachineState *machine,
> +                           RISCVBootInfo *info,
> +                           const char *firmware_filename,
>                              hwaddr *firmware_load_addr,
>                              symbol_fn_t sym_cb)
>   {
> +    uint64_t mem_size = info->ram_low_size ?: machine->ram_size;
>       uint64_t firmware_entry, firmware_end;
>       ssize_t firmware_size;
>   
> @@ -183,7 +188,7 @@ hwaddr riscv_load_firmware(const char *firmware_filename,
>   
>       firmware_size = load_image_targphys_as(firmware_filename,
>                                              *firmware_load_addr,
> -                                           current_machine->ram_size, NULL,
> +                                           mem_size, NULL,
>                                              NULL);
>   
>       if (firmware_size > 0) {
> @@ -197,7 +202,7 @@ hwaddr riscv_load_firmware(const char *firmware_filename,
>   static void riscv_load_initrd(MachineState *machine, RISCVBootInfo *info)
>   {
>       const char *filename = machine->initrd_filename;
> -    uint64_t mem_size = machine->ram_size;
> +    uint64_t mem_size = info->ram_low_size ?: machine->ram_size;
>       void *fdt = machine->fdt;
>       hwaddr start, end;
>       ssize_t size;
> @@ -243,6 +248,7 @@ void riscv_load_kernel(MachineState *machine,
>                          bool load_initrd,
>                          symbol_fn_t sym_cb)
>   {
> +    uint64_t mem_size = info->ram_low_size ?: machine->ram_size;
>       const char *kernel_filename = machine->kernel_filename;
>       ssize_t kernel_size;
>       void *fdt = machine->fdt;
> @@ -274,7 +280,7 @@ void riscv_load_kernel(MachineState *machine,
>       }
>   
>       kernel_size = load_image_targphys_as(kernel_filename, kernel_start_addr,
> -                                         current_machine->ram_size, NULL, NULL);
> +                                         mem_size, NULL, NULL);
>       if (kernel_size > 0) {
>           info->kernel_size = kernel_size;
>           info->image_low_addr = kernel_start_addr;
> @@ -370,7 +376,7 @@ uint64_t riscv_compute_fdt_addr(hwaddr dram_base, hwaddr dram_size,
>       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");
> +        error_report("Not enough memory to place DTB after kernel/initrd");
>           exit(1);
>       }
>   
> diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
> index 4ff83e494034..8905ed0ba190 100644
> --- a/hw/riscv/microchip_pfsoc.c
> +++ b/hw/riscv/microchip_pfsoc.c
> @@ -615,18 +615,20 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
>           firmware_load_addr = RESET_VECTOR;
>       }
>   
> +    riscv_boot_info_init(&boot_info, &s->soc.u_cpus);
> +
>       /* Load the firmware if necessary */
>       firmware_end_addr = firmware_load_addr;
>       if (firmware_name) {
>           char *filename = riscv_find_firmware(firmware_name, NULL);
>           if (filename) {
> -            firmware_end_addr = riscv_load_firmware(filename,
> +            firmware_end_addr = riscv_load_firmware(machine, &boot_info,
> +                                                    filename,
>                                                       &firmware_load_addr, NULL);
>               g_free(filename);
>           }
>       }
>   
> -    riscv_boot_info_init(&boot_info, &s->soc.u_cpus);
>       if (machine->kernel_filename) {
>           kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info,
>                                                            firmware_end_addr);
> diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
> index 309125e854bc..8cd660dd4154 100644
> --- a/hw/riscv/opentitan.c
> +++ b/hw/riscv/opentitan.c
> @@ -99,12 +99,14 @@ static void opentitan_machine_init(MachineState *machine)
>       memory_region_add_subregion(sys_mem,
>           memmap[IBEX_DEV_RAM].base, machine->ram);
>   
> +    riscv_boot_info_init(&boot_info, &s->soc.cpus);
> +
>       if (machine->firmware) {
>           hwaddr firmware_load_addr = memmap[IBEX_DEV_RAM].base;
> -        riscv_load_firmware(machine->firmware, &firmware_load_addr, NULL);
> +        riscv_load_firmware(machine, &boot_info, machine->firmware,
> +                            &firmware_load_addr, NULL);
>       }
>   
> -    riscv_boot_info_init(&boot_info, &s->soc.cpus);
>       if (machine->kernel_filename) {
>           riscv_load_kernel(machine, &boot_info,
>                             memmap[IBEX_DEV_RAM].base,
> diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
> index 49a39b30212d..eb720d9cdf5d 100644
> --- a/hw/riscv/shakti_c.c
> +++ b/hw/riscv/shakti_c.c
> @@ -45,6 +45,7 @@ static void shakti_c_machine_state_init(MachineState *mstate)
>   {
>       ShaktiCMachineState *sms = RISCV_SHAKTI_MACHINE(mstate);
>       MemoryRegion *system_memory = get_system_memory();
> +    RISCVBootInfo boot_info;
>       hwaddr firmware_load_addr = shakti_c_memmap[SHAKTI_C_RAM].base;
>   
>       /* Initialize SoC */
> @@ -57,8 +58,11 @@ static void shakti_c_machine_state_init(MachineState *mstate)
>                                   shakti_c_memmap[SHAKTI_C_RAM].base,
>                                   mstate->ram);
>   
> +    riscv_boot_info_init(&boot_info, &sms->soc.cpus);
> +
>       if (mstate->firmware) {
> -        riscv_load_firmware(mstate->firmware, &firmware_load_addr, NULL);
> +        riscv_load_firmware(mstate, &boot_info, mstate->firmware,
> +                            &firmware_load_addr, NULL);
>       }
>   
>       /* ROM reset vector */
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index 7ec67b256514..4c526f73edf6 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -590,7 +590,8 @@ static void sifive_u_machine_init(MachineState *machine)
>       }
>   
>       firmware_name = riscv_default_firmware_name(&s->soc.u_cpus);
> -    firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
> +    firmware_end_addr = riscv_find_and_load_firmware(machine, &boot_info,
> +                                                     firmware_name,
>                                                        &start_addr, NULL);
>   
>       riscv_boot_info_init(&boot_info, &s->soc.u_cpus);
> diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> index 1493b928dad3..86b06a173565 100644
> --- a/hw/riscv/spike.c
> +++ b/hw/riscv/spike.c
> @@ -289,9 +289,12 @@ static void spike_board_init(MachineState *machine)
>           }
>       }
>   
> +    riscv_boot_info_init(&boot_info, &s->soc[0]);
> +
>       /* Load firmware */
>       if (firmware_name) {
> -        firmware_end_addr = riscv_load_firmware(firmware_name,
> +        firmware_end_addr = riscv_load_firmware(machine, &boot_info,
> +                                                firmware_name,
>                                                   &firmware_load_addr,
>                                                   htif_symbol_callback);
>           g_free(firmware_name);
> @@ -301,7 +304,6 @@ static void spike_board_init(MachineState *machine)
>       create_fdt(s, memmap, riscv_is_32bit(&s->soc[0]), htif_custom_base);
>   
>       /* Load kernel */
> -    riscv_boot_info_init(&boot_info, &s->soc[0]);
>       if (machine->kernel_filename) {
>           kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info,
>                                                            firmware_end_addr);
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index bd8608ea5bfd..a907ca359e09 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -1466,7 +1466,10 @@ static void virt_machine_done(Notifier *notifier, void *data)
>           }
>       }
>   
> -    firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
> +    riscv_boot_info_init(&boot_info, &s->soc[0]);
> +
> +    firmware_end_addr = riscv_find_and_load_firmware(machine, &boot_info,
> +                                                     firmware_name,
>                                                        &start_addr, NULL);
>   
>       pflash_blk0 = pflash_cfi01_get_blk(s->flash[0]);
> @@ -1489,8 +1492,6 @@ static void virt_machine_done(Notifier *notifier, void *data)
>           }
>       }
>   
> -    riscv_boot_info_init(&boot_info, &s->soc[0]);
> -
>       if (machine->kernel_filename && !kernel_entry) {
>           kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info,
>                                                            firmware_end_addr);
> diff --git a/hw/riscv/xiangshan_kmh.c b/hw/riscv/xiangshan_kmh.c
> index 436e51c1c593..247a0b5d1f21 100644
> --- a/hw/riscv/xiangshan_kmh.c
> +++ b/hw/riscv/xiangshan_kmh.c
> @@ -166,6 +166,7 @@ static void xiangshan_kmh_machine_init(MachineState *machine)
>       const MemMapEntry *memmap = xiangshan_kmh_memmap;
>       MemoryRegion *system_memory = get_system_memory();
>       hwaddr start_addr = memmap[XIANGSHAN_KMH_DRAM].base;
> +    RISCVBootInfo boot_info;
>   
>       /* Initialize SoC */
>       object_initialize_child(OBJECT(machine), "soc", &s->soc,
> @@ -177,13 +178,16 @@ static void xiangshan_kmh_machine_init(MachineState *machine)
>                                   memmap[XIANGSHAN_KMH_DRAM].base,
>                                   machine->ram);
>   
> +    riscv_boot_info_init(&boot_info, &s->soc.cpus);
> +
>       /* ROM reset vector */
>       riscv_setup_rom_reset_vec(machine, &s->soc.cpus,
>                                 start_addr,
>                                 memmap[XIANGSHAN_KMH_ROM].base,
>                                 memmap[XIANGSHAN_KMH_ROM].size, 0, 0);
>       if (machine->firmware) {
> -        riscv_load_firmware(machine->firmware, &start_addr, NULL);
> +        riscv_load_firmware(machine, &boot_info, machine->firmware,
> +                            &start_addr, NULL);
>       }
>   
>       /* Note: dtb has been integrated into firmware(OpenSBI) when compiling */