[PATCH 4/4] hw/riscv/boot: Provide a simple halting payload

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 4/4] hw/riscv/boot: Provide a simple halting payload
Posted by Joel Stanley 1 month ago
From: Nicholas Piggin <npiggin@gmail.com>

OpenSBI hangs before any console output if the domain init code sees the
next stage is not in an executable region.

If no kernel payload is provided to QEMU, the next stage address is
NULL, and the riscv virt machine memory map ends up covering the 0
address with the catch all S-mode RWX region and so OpenSBI prints
console messages and does not hang until the next stage boot.

The TT Atlantis address map has RAM starting at 0 and it loads OpenSBI
there, so it is M-mode and not accessible by S-mode, tripping the early
check and hang.

Add a helper to set up a simple payload that gets OpenSBI messages
to console.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
 include/hw/riscv/boot.h |  2 ++
 hw/riscv/boot.c         | 21 +++++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index fb90bf12399e..d1d7258a2179 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -78,6 +78,8 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts
                                hwaddr rom_base, hwaddr rom_size,
                                uint64_t kernel_entry,
                                uint64_t fdt_load_addr);
+void riscv_setup_halting_payload(MachineState *machine,
+                                 RISCVBootInfo *info, hwaddr addr);
 void riscv_rom_copy_firmware_info(MachineState *machine,
                                   RISCVHartArrayState *harts,
                                   hwaddr rom_base,
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 3ea95c175c14..fc8a39a8d913 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -518,6 +518,27 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts
                                  kernel_entry);
 }
 
+/* Simple payload so OpenSBI does not hang early with no output */
+void riscv_setup_halting_payload(MachineState *machine,
+                                 RISCVBootInfo *info, hwaddr addr)
+{
+    int i;
+    uint32_t payload_vec[] = {
+        0x10500073,                     /* 1: wfi           */
+        0xffdff06f,                     /* j       1b       */
+    };
+    /* copy in the payload vector in little_endian byte order */
+    for (i = 0; i < ARRAY_SIZE(payload_vec); i++) {
+        payload_vec[i] = cpu_to_le32(payload_vec[i]);
+    }
+    rom_add_blob_fixed_as("mrom.payload", payload_vec, sizeof(payload_vec),
+                          addr, &address_space_memory);
+
+    info->kernel_size = sizeof(payload_vec);
+    info->image_low_addr = addr;
+    info->image_high_addr = info->image_low_addr + info->kernel_size;
+}
+
 void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr)
 {
     CPUState *cs;
-- 
2.47.3
Re: [PATCH 4/4] hw/riscv/boot: Provide a simple halting payload
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>
> 
> OpenSBI hangs before any console output if the domain init code sees the
> next stage is not in an executable region.
> 
> If no kernel payload is provided to QEMU, the next stage address is
> NULL, and the riscv virt machine memory map ends up covering the 0
> address with the catch all S-mode RWX region and so OpenSBI prints
> console messages and does not hang until the next stage boot.
> 
> The TT Atlantis address map has RAM starting at 0 and it loads OpenSBI
> there, so it is M-mode and not accessible by S-mode, tripping the early
> check and hang.

Please note that these patches were split from the main Atlantis series, 
meaning this patch can land upstream earlier than the main Atlantis 
board work. In this context, saying "The TT Atlantis address map has RAM 
starting at 0" makes no sense because there's no Atlantis board in QEMU.

I suggest adding something like:

"The soon to be added Tenstorrent Atlantis board address map ..."

To make it clear that, as far as this commit goes, we're talking about a 
board that will be added in future.


With this commit msg nit:


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


Thanks,

Daniel



> 
> Add a helper to set up a simple payload that gets OpenSBI messages
> to console.
> 
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
>   include/hw/riscv/boot.h |  2 ++
>   hw/riscv/boot.c         | 21 +++++++++++++++++++++
>   2 files changed, 23 insertions(+)
> 
> diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
> index fb90bf12399e..d1d7258a2179 100644
> --- a/include/hw/riscv/boot.h
> +++ b/include/hw/riscv/boot.h
> @@ -78,6 +78,8 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts
>                                  hwaddr rom_base, hwaddr rom_size,
>                                  uint64_t kernel_entry,
>                                  uint64_t fdt_load_addr);
> +void riscv_setup_halting_payload(MachineState *machine,
> +                                 RISCVBootInfo *info, hwaddr addr);
>   void riscv_rom_copy_firmware_info(MachineState *machine,
>                                     RISCVHartArrayState *harts,
>                                     hwaddr rom_base,
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> index 3ea95c175c14..fc8a39a8d913 100644
> --- a/hw/riscv/boot.c
> +++ b/hw/riscv/boot.c
> @@ -518,6 +518,27 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts
>                                    kernel_entry);
>   }
>   
> +/* Simple payload so OpenSBI does not hang early with no output */
> +void riscv_setup_halting_payload(MachineState *machine,
> +                                 RISCVBootInfo *info, hwaddr addr)
> +{
> +    int i;
> +    uint32_t payload_vec[] = {
> +        0x10500073,                     /* 1: wfi           */
> +        0xffdff06f,                     /* j       1b       */
> +    };
> +    /* copy in the payload vector in little_endian byte order */
> +    for (i = 0; i < ARRAY_SIZE(payload_vec); i++) {
> +        payload_vec[i] = cpu_to_le32(payload_vec[i]);
> +    }
> +    rom_add_blob_fixed_as("mrom.payload", payload_vec, sizeof(payload_vec),
> +                          addr, &address_space_memory);
> +
> +    info->kernel_size = sizeof(payload_vec);
> +    info->image_low_addr = addr;
> +    info->image_high_addr = info->image_low_addr + info->kernel_size;
> +}
> +
>   void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr)
>   {
>       CPUState *cs;