Commit 39968a85c6 for qemu.org

commit 39968a85c6d64490e530a02f527d80a28180478c
Author: Alistair Francis <alistair.francis@wdc.com>
Date:   Tue Jun 30 12:19:46 2026 +0930

    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>

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,