hw/riscv/boot: Account for discontiguous memory when loading firmware
This loads firmware into the first (low) memory range, accounting for machines having discontiguous memory regions. Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Joel Stanley <joel@jms.id.au> Message-ID: <20260630024952.1520546-3-joel@jms.id.au> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
committed by
Alistair Francis
parent
896c1f3d4b
commit
772ffd7ff8
@@ -151,6 +151,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)
|
||||
@@ -163,7 +164,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);
|
||||
}
|
||||
@@ -171,10 +173,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;
|
||||
|
||||
@@ -203,7 +208,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) {
|
||||
@@ -218,7 +223,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;
|
||||
@@ -264,6 +269,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;
|
||||
@@ -295,7 +301,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;
|
||||
@@ -391,7 +397,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -424,7 +424,8 @@ static void k230_direct_boot(K230MachineState *s, MachineState *machine)
|
||||
|
||||
riscv_load_fdt(K230_DIRECT_DTB_ADDR, machine->fdt);
|
||||
|
||||
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);
|
||||
if (firmware_end_addr > K230_DIRECT_KERNEL_ADDR) {
|
||||
error_report("K230 firmware overlaps kernel address 0x%x",
|
||||
@@ -442,13 +443,16 @@ static void k230_firmware_boot(K230MachineState *s, MachineState *machine)
|
||||
{
|
||||
const char *firmware_name = riscv_default_firmware_name(&s->soc.c908_cpu);
|
||||
hwaddr start_addr = memmap[K230_DEV_DDRC].base;
|
||||
RISCVBootInfo boot_info = {0};
|
||||
|
||||
if (machine->dtb || (machine->kernel_cmdline && *machine->kernel_cmdline)) {
|
||||
error_report("K230 firmware boot does not support -dtb or -append");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
riscv_find_and_load_firmware(machine, firmware_name, &start_addr, NULL);
|
||||
riscv_boot_info_init(&boot_info, &s->soc.c908_cpu);
|
||||
riscv_find_and_load_firmware(machine, &boot_info, firmware_name,
|
||||
&start_addr, NULL);
|
||||
|
||||
riscv_setup_rom_reset_vec(machine, &s->soc.c908_cpu, start_addr,
|
||||
memmap[K230_DEV_BOOTROM].base,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -524,11 +524,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);
|
||||
|
||||
@@ -205,9 +205,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);
|
||||
@@ -217,7 +220,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);
|
||||
|
||||
@@ -1310,7 +1310,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]);
|
||||
@@ -1333,8 +1336,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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user