On Wed, Jun 3, 2026 at 4:59 PM Joel Stanley <[email protected]> wrote:
>
> From: Nicholas Piggin <[email protected]>
>
> This loads firmware into the first (low) memory range,
> accounting for machines having discontiguous memory regions.
>
> Reviewed-by: Daniel Henrique Barboza <[email protected]>
> Signed-off-by: Nicholas Piggin <[email protected]>
> Signed-off-by: Joel Stanley <[email protected]>

Reviewed-by: Alistair Francis <[email protected]>

Alistair

> ---
>  include/hw/riscv/boot.h    |  5 ++++-
>  hw/riscv/boot.c            | 18 ++++++++++++------
>  hw/riscv/microchip_pfsoc.c |  8 ++++++--
>  hw/riscv/opentitan.c       |  6 ++++--
>  hw/riscv/shakti_c.c        |  6 +++++-
>  hw/riscv/sifive_u.c        |  6 ++++--
>  hw/riscv/spike.c           |  6 ++++--
>  hw/riscv/virt.c            |  7 ++++---
>  hw/riscv/xiangshan_kmh.c   |  6 +++++-
>  9 files changed, 48 insertions(+), 20 deletions(-)
>
> diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
> index 69c99a149613..4e7bd9a225ef 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,
> +                           const 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 b1a020b58aed..b0a2e384b1ae 100644
> --- a/hw/riscv/boot.c
> +++ b/hw/riscv/boot.c
> @@ -150,6 +150,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)
> @@ -162,7 +163,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);
>      }
> @@ -170,10 +172,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,
> +                           const 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;
>
> @@ -202,7 +207,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) {
> @@ -217,7 +222,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;
> @@ -263,6 +268,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;
> @@ -294,7 +300,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;
> @@ -390,7 +396,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 5e48a2970838..4017129c8304 100644
> --- a/hw/riscv/microchip_pfsoc.c
> +++ b/hw/riscv/microchip_pfsoc.c
> @@ -619,18 +619,22 @@ static void 
> microchip_icicle_kit_machine_init(MachineState *machine)
>          firmware_load_addr = RESET_VECTOR;
>      }
>
> +    riscv_boot_info_init_discontig_mem(&boot_info, &s->soc.u_cpus,
> +                                       memmap[MICROCHIP_PFSOC_DRAM_LO].base,
> +                                       mem_low_size);
> +
>      /* 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 c8b2f028f237..5b2f33d5acac 100644
> --- a/hw/riscv/opentitan.c
> +++ b/hw/riscv/opentitan.c
> @@ -100,12 +100,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 b1823a312508..835b1f879b7f 100644
> --- a/hw/riscv/shakti_c.c
> +++ b/hw/riscv/shakti_c.c
> @@ -46,6 +46,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 */
> @@ -58,8 +59,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 6a637e3b86c4..3b2763de1684 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -590,11 +590,13 @@ static void sifive_u_machine_init(MachineState *machine)
>          break;
>      }
>
> +    riscv_boot_info_init(&boot_info, &s->soc.u_cpus);
> +
>      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);
>      if (machine->kernel_filename) {
>          kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info,
>                                                           firmware_end_addr);
> diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> index f9d00e0d5c48..8d68b4e235dd 100644
> --- a/hw/riscv/spike.c
> +++ b/hw/riscv/spike.c
> @@ -282,9 +282,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);
> @@ -294,7 +297,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 ce64eaaef7d9..febf49d5f149 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -1458,7 +1458,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]);
> @@ -1481,8 +1484,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 76417ba7aba1..384624d69ad5 100644
> --- a/hw/riscv/xiangshan_kmh.c
> +++ b/hw/riscv/xiangshan_kmh.c
> @@ -167,6 +167,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,
> @@ -178,13 +179,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
>
>

Reply via email to