diff options
| author | Alistair Francis <alistair.francis@wdc.com> | 2026-06-30 12:19:46 +0930 |
|---|---|---|
| committer | Alistair Francis <alistair.francis@wdc.com> | 2026-07-01 19:59:10 +1000 |
| commit | 39968a85c6d64490e530a02f527d80a28180478c (patch) | |
| tree | 01d0b52ce4446957f0dc1afbf40d170edea4569b | |
| parent | 7778f4b27bb1068fb361ca60e6f3f9a43080619f (diff) | |
| download | qemu-39968a85c6d64490e530a02f527d80a28180478c.tar.gz qemu-39968a85c6d64490e530a02f527d80a28180478c.zip | |
hw/riscv/atlantis: Ensure OpenSBI has a non-zero next_addr
When using OpenSBI fw_dynamic on the Atlantis board OpenSBI fails
to print any output, as it hits an error early on
in the boot process and gets stuck in `sbi_hart_hang()`.
The error occurs in the `sanitize_domain()` function inside OpenSBI.
`sanitize_domain()` is called after a M-Mode OpenSBI Firmware and a generic
coverall S-Mode RWX memory region are created. `sanitize_domain()` is
checking that the next address is executable.
If no next address is provided (which occurs on QEMU with an empty payload),
then `dom->next_addr` will be 0. On most RISC-V boards address 0 will fall
inside the coverall S-Mode RWX memory region and pass this check. On
Atlantis the OpenSBI firmware is running at address 0, so this address
falls inside the M-Mode only OpenSBI firmware region and fails the check.
Once the check has failed OpenSBI aborts and the user doesn't see any
messages. This can be fixed by either supplying a payload, or just
manually forcing a non-zero address (actually just any address that
isn't the OpenSBI firmware) for next_addr.
This patch ensures that if no kernel is loaded we still specify a
default kernel_entry so that OpenSBI happily boots and jumps to
the first address in memory.
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20260630024952.1520546-9-joel@jms.id.au>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
| -rw-r--r-- | hw/riscv/tt_atlantis.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c index 1f0cd08ac9..d4fa9c251d 100644 --- a/hw/riscv/tt_atlantis.c +++ b/hw/riscv/tt_atlantis.c @@ -377,8 +377,16 @@ static void tt_atlantis_machine_done(Notifier *notifier, void *data) if (machine->kernel_filename) { riscv_load_kernel(machine, &boot_info, kernel_start_addr, true, NULL); + kernel_entry = boot_info.image_low_addr; + } else { + /* If we aren't loading a payload, OpenSBI thinks we are trying to boot + * address 0, which fails `sbi_domain_check_addr()` as that is where + * OpenSBI is running. Instead point OpenSBI to the end of the region + * where it was loaded, which avoids the early hang, allowing the + * system to proceed with the OpenSBI boot output. + */ + kernel_entry = kernel_start_addr; } - kernel_entry = boot_info.image_low_addr; fdt_load_addr = riscv_compute_fdt_addr(s->memmap[TT_ATL_DDR_LO].base, s->memmap[TT_ATL_DDR_LO].size, |
