public inbox for qemu-devel@nongnu.org
 help / color / mirror / Atom feed
* [PATCH v5 0/7] Add RISC-V big-endian target support
@ 2026-03-24 16:40 Djordje Todorovic
  2026-03-24 16:40 ` [PATCH v5 2/7] target/riscv: Set endianness MSTATUS bits at CPU reset Djordje Todorovic
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: Djordje Todorovic @ 2026-03-24 16:40 UTC (permalink / raw)
  To: qemu-devel@nongnu.org
  Cc: qemu-riscv@nongnu.org, cfu@mips.com, mst@redhat.com,
	marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com,
	philmd@linaro.org, alistair23@gmail.com, thuth@redhat.com,
	Djordje Todorovic

Adding functional test case for riscv big-endian.

Djordje Todorovic (7):
  target/riscv: Add big-endian CPU property
  target/riscv: Set endianness MSTATUS bits at CPU reset
  target/riscv: Implement runtime data endianness via MSTATUS bits
  hw/riscv: Make boot code endianness-aware at runtime
  target/riscv: Fix page table walk endianness for big-endian harts
  target/riscv: Support runtime endianness in virtio via sysemu callback
  target/riscv: Add test for RISC-V BE

 hw/riscv/boot.c                            | 82 ++++++++++++++++++----
 include/hw/riscv/boot.h                    |  2 +
 target/riscv/cpu.c                         | 22 ++++--
 target/riscv/cpu.h                         | 28 ++++++++
 target/riscv/cpu_cfg_fields.h.inc          |  1 +
 target/riscv/cpu_helper.c                  | 28 ++++++--
 target/riscv/internals.h                   |  9 +--
 target/riscv/tcg/tcg-cpu.c                 |  9 ++-
 target/riscv/translate.c                   | 12 ++--
 tests/functional/riscv64/meson.build       |  1 +
 tests/functional/riscv64/test_bigendian.py | 57 +++++++++++++++
 11 files changed, 211 insertions(+), 40 deletions(-)
 create mode 100644 tests/functional/riscv64/test_bigendian.py

-- 
2.34.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v5 1/7] target/riscv: Add big-endian CPU property
  2026-03-24 16:40 [PATCH v5 0/7] Add RISC-V big-endian target support Djordje Todorovic
  2026-03-24 16:40 ` [PATCH v5 2/7] target/riscv: Set endianness MSTATUS bits at CPU reset Djordje Todorovic
@ 2026-03-24 16:40 ` Djordje Todorovic
  2026-03-25  7:26   ` Chao Liu
  2026-03-25 10:47   ` Thomas Huth
  2026-03-24 16:40 ` [PATCH v5 5/7] target/riscv: Fix page table walk endianness for big-endian harts Djordje Todorovic
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 12+ messages in thread
From: Djordje Todorovic @ 2026-03-24 16:40 UTC (permalink / raw)
  To: qemu-devel@nongnu.org
  Cc: qemu-riscv@nongnu.org, cfu@mips.com, mst@redhat.com,
	marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com,
	philmd@linaro.org, alistair23@gmail.com, thuth@redhat.com,
	Djordje Todorovic

Add a "big-endian" boolean property to the RISC-V CPU configuration,
defaulting to false (little-endian). This property allows machine
models to configure individual HARTs for big-endian data operation.

The RISC-V ISA supports big-endian data accesses via the mstatus
SBE/MBE/UBE bits, while instructions remain always little-endian.
This property provides the configuration interface; subsequent
patches will connect it to the CPU state and translation logic.

Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
---
 target/riscv/cpu.c                | 1 +
 target/riscv/cpu_cfg_fields.h.inc | 1 +
 2 files changed, 2 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e56470a374..4537305dfe 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -2641,6 +2641,7 @@ RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[] = {
 
 static const Property riscv_cpu_properties[] = {
     DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
+    DEFINE_PROP_BOOL("big-endian", RISCVCPU, cfg.big_endian, false),
 
     {.name = "pmu-mask", .info = &prop_pmu_mask},
     {.name = "pmu-num", .info = &prop_pmu_num}, /* Deprecated */
diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc
index 70ec650abf..51436daabf 100644
--- a/target/riscv/cpu_cfg_fields.h.inc
+++ b/target/riscv/cpu_cfg_fields.h.inc
@@ -154,6 +154,7 @@ BOOL_FIELD(ext_xmipscbop)
 BOOL_FIELD(ext_xmipscmov)
 BOOL_FIELD(ext_xmipslsp)
 
+BOOL_FIELD(big_endian)
 BOOL_FIELD(mmu)
 BOOL_FIELD(pmp)
 BOOL_FIELD(debug)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 2/7] target/riscv: Set endianness MSTATUS bits at CPU reset
  2026-03-24 16:40 [PATCH v5 0/7] Add RISC-V big-endian target support Djordje Todorovic
@ 2026-03-24 16:40 ` Djordje Todorovic
  2026-03-24 16:40 ` [PATCH v5 1/7] target/riscv: Add big-endian CPU property Djordje Todorovic
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Djordje Todorovic @ 2026-03-24 16:40 UTC (permalink / raw)
  To: qemu-devel@nongnu.org
  Cc: qemu-riscv@nongnu.org, cfu@mips.com, mst@redhat.com,
	marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com,
	philmd@linaro.org, alistair23@gmail.com, thuth@redhat.com,
	Djordje Todorovic

When the big-endian CPU property is enabled, set the MSTATUS_UBE
(User Big-Endian), MSTATUS_SBE (Supervisor Big-Endian), and
MSTATUS_MBE (Machine Big-Endian) bits during CPU reset.

This configures all privilege levels for big-endian data access,
matching the RISC-V privileged specification's endianness control
mechanism. Instructions remain little-endian regardless.

Also update the disassembler comment to clarify that
BFD_ENDIAN_LITTLE is correct because RISC-V instructions are
always little-endian per the ISA specification.

Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
---
 target/riscv/cpu.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 4537305dfe..eed5afd27e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -716,6 +716,9 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
             env->mstatus = set_field(env->mstatus, MSTATUS_MDT, 1);
         }
     }
+    if (cpu->cfg.big_endian) {
+        env->mstatus |= MSTATUS_UBE | MSTATUS_SBE | MSTATUS_MBE;
+    }
     env->mcause = 0;
     env->miclaim = MIP_SGEIP;
     env->pc = env->resetvec;
@@ -803,11 +806,8 @@ static void riscv_cpu_disas_set_info(const CPUState *s, disassemble_info *info)
     info->target_info = &cpu->cfg;
 
     /*
-     * A couple of bits in MSTATUS set the endianness:
-     *  - MSTATUS_UBE (User-mode),
-     *  - MSTATUS_SBE (Supervisor-mode),
-     *  - MSTATUS_MBE (Machine-mode)
-     * but we don't implement that yet.
+     * RISC-V instructions are always little-endian, regardless of the
+     * data endianness configured via MSTATUS UBE/SBE/MBE bits.
      */
     info->endian = BFD_ENDIAN_LITTLE;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 5/7] target/riscv: Fix page table walk endianness for big-endian harts
  2026-03-24 16:40 [PATCH v5 0/7] Add RISC-V big-endian target support Djordje Todorovic
  2026-03-24 16:40 ` [PATCH v5 2/7] target/riscv: Set endianness MSTATUS bits at CPU reset Djordje Todorovic
  2026-03-24 16:40 ` [PATCH v5 1/7] target/riscv: Add big-endian CPU property Djordje Todorovic
@ 2026-03-24 16:40 ` Djordje Todorovic
  2026-03-24 16:40 ` [PATCH v5 3/7] target/riscv: Implement runtime data endianness via MSTATUS bits Djordje Todorovic
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Djordje Todorovic @ 2026-03-24 16:40 UTC (permalink / raw)
  To: qemu-devel@nongnu.org
  Cc: qemu-riscv@nongnu.org, cfu@mips.com, mst@redhat.com,
	marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com,
	philmd@linaro.org, alistair23@gmail.com, thuth@redhat.com,
	Djordje Todorovic

The page table walker reads PTEs using address_space_ldl/ldq which use
compile-time native endianness (always LE for RISC-V). However, when a
big-endian kernel writes PTEs via normal store instructions, they are
stored in big-endian byte order. The walker then misinterprets the PTE
values, causing page faults and a hang when the kernel enables the MMU.

The RISC-V privileged specification states that implicit data memory
accesses to supervisor-level memory management data structures follow
the hart's endianness setting (MSTATUS SBE/MBE bits).

Fix both PTE reads and atomic A/D bit updates to use the explicit _le
or _be memory access variants based on the hart's runtime endianness.

Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 target/riscv/cpu_helper.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index c28832e0e3..b3d33da13e 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1365,9 +1365,13 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         }
 
         if (riscv_cpu_mxl(env) == MXL_RV32) {
-            pte = address_space_ldl_le(cs->as, pte_addr, attrs, &res);
+            pte = riscv_cpu_data_is_big_endian(env)
+                ? address_space_ldl_be(cs->as, pte_addr, attrs, &res)
+                : address_space_ldl_le(cs->as, pte_addr, attrs, &res);
         } else {
-            pte = address_space_ldq_le(cs->as, pte_addr, attrs, &res);
+            pte = riscv_cpu_data_is_big_endian(env)
+                ? address_space_ldq_be(cs->as, pte_addr, attrs, &res)
+                : address_space_ldq_le(cs->as, pte_addr, attrs, &res);
         }
 
         if (res != MEMTX_OK) {
@@ -1566,12 +1570,24 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         if (memory_region_is_ram(mr)) {
             target_ulong *pte_pa = qemu_map_ram_ptr(mr->ram_block, addr1);
             target_ulong old_pte;
+            bool be = riscv_cpu_data_is_big_endian(env);
             if (riscv_cpu_sxl(env) == MXL_RV32) {
-                old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, cpu_to_le32(pte), cpu_to_le32(updated_pte));
-                old_pte = le32_to_cpu(old_pte);
+                uint32_t cmp = be ? cpu_to_be32(pte)
+                                  : cpu_to_le32(pte);
+                uint32_t val = be ? cpu_to_be32(updated_pte)
+                                  : cpu_to_le32(updated_pte);
+                old_pte = qatomic_cmpxchg((uint32_t *)pte_pa,
+                                          cmp, val);
+                old_pte = be ? be32_to_cpu(old_pte)
+                             : le32_to_cpu(old_pte);
             } else {
-                old_pte = qatomic_cmpxchg(pte_pa, cpu_to_le64(pte), cpu_to_le64(updated_pte));
-                old_pte = le64_to_cpu(old_pte);
+                target_ulong cmp = be ? cpu_to_be64(pte)
+                                      : cpu_to_le64(pte);
+                target_ulong val = be ? cpu_to_be64(updated_pte)
+                                      : cpu_to_le64(updated_pte);
+                old_pte = qatomic_cmpxchg(pte_pa, cmp, val);
+                old_pte = be ? be64_to_cpu(old_pte)
+                             : le64_to_cpu(old_pte);
             }
             if (old_pte != pte) {
                 goto restart;
-- 
2.34.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 4/7] hw/riscv: Make boot code endianness-aware at runtime
  2026-03-24 16:40 [PATCH v5 0/7] Add RISC-V big-endian target support Djordje Todorovic
                   ` (3 preceding siblings ...)
  2026-03-24 16:40 ` [PATCH v5 3/7] target/riscv: Implement runtime data endianness via MSTATUS bits Djordje Todorovic
@ 2026-03-24 16:40 ` Djordje Todorovic
  2026-03-24 16:40 ` [PATCH v5 6/7] target/riscv: Support runtime endianness in virtio via sysemu callback Djordje Todorovic
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Djordje Todorovic @ 2026-03-24 16:40 UTC (permalink / raw)
  To: qemu-devel@nongnu.org
  Cc: qemu-riscv@nongnu.org, cfu@mips.com, mst@redhat.com,
	marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com,
	philmd@linaro.org, alistair23@gmail.com, thuth@redhat.com,
	Djordje Todorovic

Add riscv_is_big_endian() helper that checks the hart's big-endian CPU
property and use it throughout the boot code:

- ELF loading: pass ELFDATA2MSB or ELFDATA2LSB based on endianness
- Firmware dynamic info: use cpu_to_be* or cpu_to_le* based on endianness
- Reset vector: instructions (entries 0-5) remain always little-endian,
  data words (entries 6-9) use target data endianness. For RV64 BE, the
  hi/lo word pairs within each dword are swapped since LD reads as BE.

This is part of the runtime big-endian support series which avoids
separate BE binaries by handling endianness as a CPU property.

Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
---
 hw/riscv/boot.c         | 82 +++++++++++++++++++++++++++++++++++------
 include/hw/riscv/boot.h |  2 +
 2 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index e5490beda0..c7558b904f 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -40,6 +40,28 @@ bool riscv_is_32bit(RISCVHartArrayState *harts)
     return mcc->def->misa_mxl_max == MXL_RV32;
 }
 
+bool riscv_is_big_endian(RISCVHartArrayState *harts)
+{
+    return harts->harts[0].cfg.big_endian;
+}
+
+/*
+ * Convert a pair of 32-bit words forming a 64-bit dword to target data
+ * endianness. For big-endian, the hi/lo word order is swapped since LD
+ * interprets bytes as BE.
+ */
+static void riscv_boot_data_dword(uint32_t *data, bool big_endian)
+{
+    if (big_endian) {
+        uint32_t tmp = data[0];
+        data[0] = cpu_to_be32(data[1]);
+        data[1] = cpu_to_be32(tmp);
+    } else {
+        data[0] = cpu_to_le32(data[0]);
+        data[1] = cpu_to_le32(data[1]);
+    }
+}
+
 /*
  * Return the per-socket PLIC hart topology configuration string
  * (caller must free with g_free())
@@ -72,6 +94,7 @@ void riscv_boot_info_init(RISCVBootInfo *info, RISCVHartArrayState *harts)
     info->kernel_size = 0;
     info->initrd_size = 0;
     info->is_32bit = riscv_is_32bit(harts);
+    info->is_big_endian = riscv_is_big_endian(harts);
 }
 
 vaddr riscv_calc_kernel_start_addr(RISCVBootInfo *info,
@@ -247,8 +270,9 @@ void riscv_load_kernel(MachineState *machine,
      */
     kernel_size = load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, NULL,
                                    &info->image_low_addr, &info->image_high_addr,
-                                   NULL, ELFDATA2LSB, EM_RISCV,
-                                   1, 0, NULL, true, sym_cb);
+                                   NULL,
+                                   ELFDATA2LSB,
+                                   EM_RISCV, 1, 0, NULL, true, sym_cb);
     if (kernel_size > 0) {
         info->kernel_size = kernel_size;
         goto out;
@@ -391,21 +415,32 @@ void riscv_rom_copy_firmware_info(MachineState *machine,
     struct fw_dynamic_info64 dinfo64;
     void *dinfo_ptr = NULL;
     size_t dinfo_len;
+    bool big_endian = riscv_is_big_endian(harts);
 
     if (riscv_is_32bit(harts)) {
-        dinfo32.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
-        dinfo32.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
-        dinfo32.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
-        dinfo32.next_addr = cpu_to_le32(kernel_entry);
+        dinfo32.magic = big_endian ? cpu_to_be32(FW_DYNAMIC_INFO_MAGIC_VALUE)
+                                   : cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
+        dinfo32.version = big_endian ? cpu_to_be32(FW_DYNAMIC_INFO_VERSION)
+                                     : cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
+        dinfo32.next_mode = big_endian
+                          ? cpu_to_be32(FW_DYNAMIC_INFO_NEXT_MODE_S)
+                          : cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
+        dinfo32.next_addr = big_endian ? cpu_to_be32(kernel_entry)
+                                       : cpu_to_le32(kernel_entry);
         dinfo32.options = 0;
         dinfo32.boot_hart = 0;
         dinfo_ptr = &dinfo32;
         dinfo_len = sizeof(dinfo32);
     } else {
-        dinfo64.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
-        dinfo64.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
-        dinfo64.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
-        dinfo64.next_addr = cpu_to_le64(kernel_entry);
+        dinfo64.magic = big_endian ? cpu_to_be64(FW_DYNAMIC_INFO_MAGIC_VALUE)
+                                   : cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
+        dinfo64.version = big_endian ? cpu_to_be64(FW_DYNAMIC_INFO_VERSION)
+                                     : cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
+        dinfo64.next_mode = big_endian
+                          ? cpu_to_be64(FW_DYNAMIC_INFO_NEXT_MODE_S)
+                          : cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
+        dinfo64.next_addr = big_endian ? cpu_to_be64(kernel_entry)
+                                       : cpu_to_le64(kernel_entry);
         dinfo64.options = 0;
         dinfo64.boot_hart = 0;
         dinfo_ptr = &dinfo64;
@@ -474,10 +509,33 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts
         reset_vec[2] = 0x00000013;   /*     addi   x0, x0, 0 */
     }
 
-    /* copy in the reset vector in little_endian byte order */
-    for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
+    /* RISC-V instructions are always little-endian */
+    for (i = 0; i < 6; i++) {
         reset_vec[i] = cpu_to_le32(reset_vec[i]);
     }
+
+    /*
+     * Data words (addresses at entries 6-9) must match the firmware's data
+     * endianness.
+     */
+    if (riscv_is_32bit(harts)) {
+        for (i = 6; i < ARRAY_SIZE(reset_vec); i++) {
+            if (riscv_is_big_endian(harts)) {
+                reset_vec[i] = cpu_to_be32(reset_vec[i]);
+            } else {
+                reset_vec[i] = cpu_to_le32(reset_vec[i]);
+            }
+        }
+    } else {
+        /*
+         * For RV64, each pair of 32-bit words forms a dword. For big-endian,
+         * the hi/lo word order within each dword must be swapped since LD
+         * interprets bytes as BE.
+         */
+        for (i = 6; i < ARRAY_SIZE(reset_vec); i += 2) {
+            riscv_boot_data_dword(reset_vec + i, riscv_is_big_endian(harts));
+        }
+    }
     rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
                           rom_base, &address_space_memory);
     riscv_rom_copy_firmware_info(machine, harts,
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index f00b3ca122..a54c2b397d 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -36,9 +36,11 @@ typedef struct RISCVBootInfo {
     ssize_t initrd_size;
 
     bool is_32bit;
+    bool is_big_endian;
 } RISCVBootInfo;
 
 bool riscv_is_32bit(RISCVHartArrayState *harts);
+bool riscv_is_big_endian(RISCVHartArrayState *harts);
 
 char *riscv_plic_hart_config_string(int hart_count);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 3/7] target/riscv: Implement runtime data endianness via MSTATUS bits
  2026-03-24 16:40 [PATCH v5 0/7] Add RISC-V big-endian target support Djordje Todorovic
                   ` (2 preceding siblings ...)
  2026-03-24 16:40 ` [PATCH v5 5/7] target/riscv: Fix page table walk endianness for big-endian harts Djordje Todorovic
@ 2026-03-24 16:40 ` Djordje Todorovic
  2026-03-24 16:40 ` [PATCH v5 4/7] hw/riscv: Make boot code endianness-aware at runtime Djordje Todorovic
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Djordje Todorovic @ 2026-03-24 16:40 UTC (permalink / raw)
  To: qemu-devel@nongnu.org
  Cc: qemu-riscv@nongnu.org, cfu@mips.com, mst@redhat.com,
	marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com,
	philmd@linaro.org, alistair23@gmail.com, thuth@redhat.com,
	Djordje Todorovic

Implement runtime big-endian data support by reading the MSTATUS
UBE/SBE/MBE bits to determine data endianness per privilege level.

The key changes are:

- Add riscv_cpu_data_is_big_endian() helper in cpu.h that checks
  the appropriate MSTATUS endianness bit based on current privilege
  level (MBE for M-mode, SBE for S-mode, UBE for U-mode).

- Update mo_endian() in translate.c to return MO_BE or MO_LE based
  on a new 'big_endian' field in DisasContext, rather than the
  previous hardcoded MO_TE.

- Update mo_endian_env() in op_helper.c to call the new helper,
  giving hypervisor load/store helpers correct runtime endianness.

- Pack the endianness flag into cs_base bit 32 (alongside misa_ext
  in bits 0-25) in riscv_get_tb_cpu_state(), ensuring translation
  blocks are correctly separated by data endianness.

Note: instruction fetches continue to use MO_LE unconditionally
(from the previous patch), as RISC-V instructions are always
little-endian per the ISA specification.

Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
---
 target/riscv/cpu.h         | 28 ++++++++++++++++++++++++++++
 target/riscv/internals.h   |  9 +--------
 target/riscv/tcg/tcg-cpu.c |  9 ++++++++-
 target/riscv/translate.c   | 12 ++++--------
 4 files changed, 41 insertions(+), 17 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 35d1f6362c..ef870d05b3 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -703,6 +703,12 @@ FIELD(TB_FLAGS, BCFI_ENABLED, 28, 1)
 FIELD(TB_FLAGS, PM_PMM, 29, 2)
 FIELD(TB_FLAGS, PM_SIGNEXTEND, 31, 1)
 
+/*
+ * cs_base carries misa_ext (bits 0-25) plus additional flags.
+ * Bit 32 is used for data endianness since TB_FLAGS has no free bits.
+ */
+#define TB_CSBASE_BIG_ENDIAN  (1ULL << 32)
+
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
 #else
@@ -718,6 +724,28 @@ static inline const RISCVCPUConfig *riscv_cpu_cfg(CPURISCVState *env)
     return &env_archcpu(env)->cfg;
 }
 
+/*
+ * Return true if data accesses are big-endian for the current privilege
+ * level, based on the MSTATUS MBE/SBE/UBE bits.
+ */
+static inline bool riscv_cpu_data_is_big_endian(CPURISCVState *env)
+{
+#if defined(CONFIG_USER_ONLY)
+    return false;
+#else
+    switch (env->priv) {
+    case PRV_M:
+        return env->mstatus & MSTATUS_MBE;
+    case PRV_S:
+        return env->mstatus & MSTATUS_SBE;
+    case PRV_U:
+        return env->mstatus & MSTATUS_UBE;
+    default:
+        g_assert_not_reached();
+    }
+#endif
+}
+
 #if !defined(CONFIG_USER_ONLY)
 static inline int cpu_address_mode(CPURISCVState *env)
 {
diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index 460346dd6d..e2f0334da8 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -64,14 +64,7 @@ static inline bool mmuidx_2stage(int mmu_idx)
 
 static inline MemOp mo_endian_env(CPURISCVState *env)
 {
-    /*
-     * A couple of bits in MSTATUS set the endianness:
-     *  - MSTATUS_UBE (User-mode),
-     *  - MSTATUS_SBE (Supervisor-mode),
-     *  - MSTATUS_MBE (Machine-mode)
-     * but we don't implement that yet.
-     */
-    return MO_LE;
+    return riscv_cpu_data_is_big_endian(env) ? MO_BE : MO_LE;
 }
 
 /* share data between vector helpers and decode code */
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 3407191c22..fa42197e98 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -189,10 +189,17 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
     flags = FIELD_DP32(flags, TB_FLAGS, PM_PMM, riscv_pm_get_pmm(env));
     flags = FIELD_DP32(flags, TB_FLAGS, PM_SIGNEXTEND, pm_signext);
 
+    uint64_t cs_base = env->misa_ext;
+#ifndef CONFIG_USER_ONLY
+    if (riscv_cpu_data_is_big_endian(env)) {
+        cs_base |= TB_CSBASE_BIG_ENDIAN;
+    }
+#endif
+
     return (TCGTBCPUState){
         .pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc,
         .flags = flags,
-        .cs_base = env->misa_ext,
+        .cs_base = cs_base,
     };
 }
 
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 5df5b73849..d7f1f8e466 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -119,6 +119,8 @@ typedef struct DisasContext {
     bool fcfi_lp_expected;
     /* zicfiss extension, if shadow stack was enabled during TB gen */
     bool bcfi_enabled;
+    /* Data endianness from MSTATUS UBE/SBE/MBE */
+    bool big_endian;
 } DisasContext;
 
 static inline bool has_ext(DisasContext *ctx, uint32_t ext)
@@ -128,14 +130,7 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext)
 
 static inline MemOp mo_endian(DisasContext *ctx)
 {
-    /*
-     * A couple of bits in MSTATUS set the endianness:
-     *  - MSTATUS_UBE (User-mode),
-     *  - MSTATUS_SBE (Supervisor-mode),
-     *  - MSTATUS_MBE (Machine-mode)
-     * but we don't implement that yet.
-     */
-    return MO_LE;
+    return ctx->big_endian ? MO_BE : MO_LE;
 }
 
 #ifdef TARGET_RISCV32
@@ -1346,6 +1341,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->zero = tcg_constant_tl(0);
     ctx->virt_inst_excp = false;
     ctx->decoders = cpu->decoders;
+    ctx->big_endian = ctx->base.tb->cs_base & TB_CSBASE_BIG_ENDIAN;
 }
 
 static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 6/7] target/riscv: Support runtime endianness in virtio via sysemu callback
  2026-03-24 16:40 [PATCH v5 0/7] Add RISC-V big-endian target support Djordje Todorovic
                   ` (4 preceding siblings ...)
  2026-03-24 16:40 ` [PATCH v5 4/7] hw/riscv: Make boot code endianness-aware at runtime Djordje Todorovic
@ 2026-03-24 16:40 ` Djordje Todorovic
  2026-03-24 16:40 ` [PATCH v5 7/7] target/riscv: Add test for RISC-V BE Djordje Todorovic
  2026-03-25  3:58 ` [PATCH v5 0/7] Add RISC-V big-endian target support Chao Liu
  7 siblings, 0 replies; 12+ messages in thread
From: Djordje Todorovic @ 2026-03-24 16:40 UTC (permalink / raw)
  To: qemu-devel@nongnu.org
  Cc: qemu-riscv@nongnu.org, cfu@mips.com, mst@redhat.com,
	marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com,
	philmd@linaro.org, alistair23@gmail.com, thuth@redhat.com,
	Djordje Todorovic

Implement the .virtio_is_big_endian SysemuCPUOps callback for RISC-V.
This makes cpu_virtio_is_big_endian() return the correct endianness
based on the hart's MSTATUS MBE/SBE/UBE bits, which is used by
virtio_current_cpu_endian() during guest-initiated device resets.

For bi-endian RISC-V targets, this ensures legacy virtio devices
correctly detect the guest's runtime data endianness, matching
how ARM handles its bi-endian support.

Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
---
 target/riscv/cpu.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eed5afd27e..f813acf579 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -32,6 +32,7 @@
 #include "migration/vmstate.h"
 #include "fpu/softfloat-helpers.h"
 #include "system/device_tree.h"
+#include "system/hw_accel.h"
 #include "system/kvm.h"
 #include "system/tcg.h"
 #include "kvm/kvm_riscv.h"
@@ -2713,11 +2714,21 @@ static int64_t riscv_get_arch_id(CPUState *cs)
 
 #include "hw/core/sysemu-cpu-ops.h"
 
+static bool riscv_cpu_virtio_is_big_endian(CPUState *cs)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+
+    cpu_synchronize_state(cs);
+    return riscv_cpu_data_is_big_endian(env);
+}
+
 static const struct SysemuCPUOps riscv_sysemu_ops = {
     .has_work = riscv_cpu_has_work,
     .get_phys_page_debug = riscv_cpu_get_phys_page_debug,
     .write_elf64_note = riscv_cpu_write_elf64_note,
     .write_elf32_note = riscv_cpu_write_elf32_note,
+    .internal_is_big_endian = riscv_cpu_virtio_is_big_endian,
     .legacy_vmsd = &vmstate_riscv_cpu,
 };
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 7/7] target/riscv: Add test for RISC-V BE
  2026-03-24 16:40 [PATCH v5 0/7] Add RISC-V big-endian target support Djordje Todorovic
                   ` (5 preceding siblings ...)
  2026-03-24 16:40 ` [PATCH v5 6/7] target/riscv: Support runtime endianness in virtio via sysemu callback Djordje Todorovic
@ 2026-03-24 16:40 ` Djordje Todorovic
  2026-03-25 10:51   ` Thomas Huth
  2026-03-25  3:58 ` [PATCH v5 0/7] Add RISC-V big-endian target support Chao Liu
  7 siblings, 1 reply; 12+ messages in thread
From: Djordje Todorovic @ 2026-03-24 16:40 UTC (permalink / raw)
  To: qemu-devel@nongnu.org
  Cc: qemu-riscv@nongnu.org, cfu@mips.com, mst@redhat.com,
	marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com,
	philmd@linaro.org, alistair23@gmail.com, thuth@redhat.com,
	Djordje Todorovic

Add functional test for RISC-V big-endian.

Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
---
 tests/functional/riscv64/meson.build       |  1 +
 tests/functional/riscv64/test_bigendian.py | 57 ++++++++++++++++++++++
 2 files changed, 58 insertions(+)
 create mode 100644 tests/functional/riscv64/test_bigendian.py

diff --git a/tests/functional/riscv64/meson.build b/tests/functional/riscv64/meson.build
index b996c89d7d..d06d6ea112 100644
--- a/tests/functional/riscv64/meson.build
+++ b/tests/functional/riscv64/meson.build
@@ -11,6 +11,7 @@ tests_riscv64_system_quick = [
 ]
 
 tests_riscv64_system_thorough = [
+  'bigendian',
   'boston',
   'sifive_u',
   'tuxrun',
diff --git a/tests/functional/riscv64/test_bigendian.py b/tests/functional/riscv64/test_bigendian.py
new file mode 100644
index 0000000000..9e0b3b7db5
--- /dev/null
+++ b/tests/functional/riscv64/test_bigendian.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+#
+# Functional tests for RISC-V big-endian support
+#
+# Copyright (c) 2026 MIPS
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import QemuSystemTest, Asset
+from qemu_test import wait_for_console_pattern
+
+
+class RiscvBigEndian(QemuSystemTest):
+    """
+    Tests for RISC-V runtime big-endian data support.
+
+    Uses a bare-metal RV64 ELF that detects data endianness at runtime
+    by storing a 32-bit word and reading back byte 0. Prints "ENDIAN: BE"
+    or "ENDIAN: LE" to the NS16550A UART on the virt machine.
+    """
+
+    timeout = 10
+
+    ASSET_BE_TEST = Asset(
+        'https://github.com/MIPS/linux-test-downloads/raw/main/'
+        'riscvbe-baremetal/be-test-bare-metal.elf',
+        '9ad51b675e101de65908fadbac064ed1d0564c17463715d09dd734db86ea0f58')
+
+    def _run_bare_metal(self, big_endian=False):
+        self.set_machine('virt')
+        kernel = self.ASSET_BE_TEST.fetch()
+        self.vm.add_args('-bios', 'none')
+        self.vm.add_args('-kernel', kernel)
+        if big_endian:
+            self.vm.add_args('-cpu', 'rv64,big-endian=on')
+        self.vm.set_console()
+        self.vm.launch()
+        expected = 'ENDIAN: BE' if big_endian else 'ENDIAN: LE'
+        wait_for_console_pattern(self, expected)
+
+    def test_bare_metal_littleendian(self):
+        """
+        Boot bare-metal ELF on virt with default little-endian CPU.
+        Expects "ENDIAN: LE" on UART.
+        """
+        self._run_bare_metal(big_endian=False)
+
+    def test_bare_metal_bigendian(self):
+        """
+        Boot bare-metal ELF on virt with big-endian=on CPU property.
+        Expects "ENDIAN: BE" on UART.
+        """
+        self._run_bare_metal(big_endian=True)
+
+
+if __name__ == '__main__':
+    QemuSystemTest.main()
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 0/7] Add RISC-V big-endian target support
  2026-03-24 16:40 [PATCH v5 0/7] Add RISC-V big-endian target support Djordje Todorovic
                   ` (6 preceding siblings ...)
  2026-03-24 16:40 ` [PATCH v5 7/7] target/riscv: Add test for RISC-V BE Djordje Todorovic
@ 2026-03-25  3:58 ` Chao Liu
  7 siblings, 0 replies; 12+ messages in thread
From: Chao Liu @ 2026-03-25  3:58 UTC (permalink / raw)
  To: Djordje Todorovic
  Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org, cfu@mips.com,
	mst@redhat.com, marcel.apfelbaum@gmail.com,
	dbarboza@ventanamicro.com, philmd@linaro.org,
	alistair23@gmail.com, thuth@redhat.com

Hi Djordje,

On Tue, Mar 24, 2026 at 04:40:14PM +0000, Djordje Todorovic wrote:
> Adding functional test case for riscv big-endian.
> 
Thanks for the v5 and for adding the functional test
that Philippe requested. The runtime big-endian approach
is the right direction.

However, it looks like the series was developed on top
of Philippe's "[PATCH-for-11.1] target/riscv: Forbid to
use legacy native endianness API" prep series, which
hasn't been merged yet. This causes two build-breaking
issues and apply failures on both master and
riscv-to-apply.next.

For v6, I'd suggest either:
a) Explicitly declare "Based-on:" Philippe's prep
   series, or

b) Include the prerequisite changes (MSTATUS defines,
   op_helper.c cleanup, MO_TE->MO_LE) in this series.

Thanks,
Chao
> Djordje Todorovic (7):
>   target/riscv: Add big-endian CPU property
>   target/riscv: Set endianness MSTATUS bits at CPU reset
>   target/riscv: Implement runtime data endianness via MSTATUS bits
>   hw/riscv: Make boot code endianness-aware at runtime
>   target/riscv: Fix page table walk endianness for big-endian harts
>   target/riscv: Support runtime endianness in virtio via sysemu callback
>   target/riscv: Add test for RISC-V BE
> 
>  hw/riscv/boot.c                            | 82 ++++++++++++++++++----
>  include/hw/riscv/boot.h                    |  2 +
>  target/riscv/cpu.c                         | 22 ++++--
>  target/riscv/cpu.h                         | 28 ++++++++
>  target/riscv/cpu_cfg_fields.h.inc          |  1 +
>  target/riscv/cpu_helper.c                  | 28 ++++++--
>  target/riscv/internals.h                   |  9 +--
>  target/riscv/tcg/tcg-cpu.c                 |  9 ++-
>  target/riscv/translate.c                   | 12 ++--
>  tests/functional/riscv64/meson.build       |  1 +
>  tests/functional/riscv64/test_bigendian.py | 57 +++++++++++++++
>  11 files changed, 211 insertions(+), 40 deletions(-)
>  create mode 100644 tests/functional/riscv64/test_bigendian.py
> 
> -- 
> 2.34.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 1/7] target/riscv: Add big-endian CPU property
  2026-03-24 16:40 ` [PATCH v5 1/7] target/riscv: Add big-endian CPU property Djordje Todorovic
@ 2026-03-25  7:26   ` Chao Liu
  2026-03-25 10:47   ` Thomas Huth
  1 sibling, 0 replies; 12+ messages in thread
From: Chao Liu @ 2026-03-25  7:26 UTC (permalink / raw)
  To: Djordje Todorovic
  Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org, cfu@mips.com,
	mst@redhat.com, marcel.apfelbaum@gmail.com,
	dbarboza@ventanamicro.com, philmd@linaro.org,
	alistair23@gmail.com, thuth@redhat.com

On Tue, Mar 24, 2026 at 04:40:15PM +0000, Djordje Todorovic wrote:
> Add a "big-endian" boolean property to the RISC-V CPU configuration,
> defaulting to false (little-endian). This property allows machine
> models to configure individual HARTs for big-endian data operation.
> 
> The RISC-V ISA supports big-endian data accesses via the mstatus
> SBE/MBE/UBE bits, while instructions remain always little-endian.
> This property provides the configuration interface; subsequent
> patches will connect it to the CPU state and translation logic.
> 
LGTM.

Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>

Thanks,
Chao
> Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
> ---
>  target/riscv/cpu.c                | 1 +
>  target/riscv/cpu_cfg_fields.h.inc | 1 +
>  2 files changed, 2 insertions(+)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index e56470a374..4537305dfe 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -2641,6 +2641,7 @@ RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[] = {
>  
>  static const Property riscv_cpu_properties[] = {
>      DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
> +    DEFINE_PROP_BOOL("big-endian", RISCVCPU, cfg.big_endian, false),
>  
>      {.name = "pmu-mask", .info = &prop_pmu_mask},
>      {.name = "pmu-num", .info = &prop_pmu_num}, /* Deprecated */
> diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc
> index 70ec650abf..51436daabf 100644
> --- a/target/riscv/cpu_cfg_fields.h.inc
> +++ b/target/riscv/cpu_cfg_fields.h.inc
> @@ -154,6 +154,7 @@ BOOL_FIELD(ext_xmipscbop)
>  BOOL_FIELD(ext_xmipscmov)
>  BOOL_FIELD(ext_xmipslsp)
>  
> +BOOL_FIELD(big_endian)
>  BOOL_FIELD(mmu)
>  BOOL_FIELD(pmp)
>  BOOL_FIELD(debug)
> -- 
> 2.34.1
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 1/7] target/riscv: Add big-endian CPU property
  2026-03-24 16:40 ` [PATCH v5 1/7] target/riscv: Add big-endian CPU property Djordje Todorovic
  2026-03-25  7:26   ` Chao Liu
@ 2026-03-25 10:47   ` Thomas Huth
  1 sibling, 0 replies; 12+ messages in thread
From: Thomas Huth @ 2026-03-25 10:47 UTC (permalink / raw)
  To: Djordje Todorovic, qemu-devel@nongnu.org
  Cc: qemu-riscv@nongnu.org, cfu@mips.com, mst@redhat.com,
	marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com,
	philmd@linaro.org, alistair23@gmail.com

On 24/03/2026 17.40, Djordje Todorovic wrote:
> Add a "big-endian" boolean property to the RISC-V CPU configuration,
> defaulting to false (little-endian). This property allows machine
> models to configure individual HARTs for big-endian data operation.
> 
> The RISC-V ISA supports big-endian data accesses via the mstatus
> SBE/MBE/UBE bits, while instructions remain always little-endian.
> This property provides the configuration interface; subsequent
> patches will connect it to the CPU state and translation logic.
> 
> Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
> ---
>   target/riscv/cpu.c                | 1 +
>   target/riscv/cpu_cfg_fields.h.inc | 1 +
>   2 files changed, 2 insertions(+)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index e56470a374..4537305dfe 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -2641,6 +2641,7 @@ RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[] = {
>   
>   static const Property riscv_cpu_properties[] = {
>       DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
> +    DEFINE_PROP_BOOL("big-endian", RISCVCPU, cfg.big_endian, false),

Note that there is also a DEFINE_PROP_ENDIAN available ... not sure whether 
it's a better fit here, though. Maybe mention in the patch description why 
BOOL is better than ENDIAN here?

  Thomas



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 7/7] target/riscv: Add test for RISC-V BE
  2026-03-24 16:40 ` [PATCH v5 7/7] target/riscv: Add test for RISC-V BE Djordje Todorovic
@ 2026-03-25 10:51   ` Thomas Huth
  0 siblings, 0 replies; 12+ messages in thread
From: Thomas Huth @ 2026-03-25 10:51 UTC (permalink / raw)
  To: Djordje Todorovic, qemu-devel@nongnu.org
  Cc: qemu-riscv@nongnu.org, cfu@mips.com, mst@redhat.com,
	marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com,
	philmd@linaro.org, alistair23@gmail.com

On 24/03/2026 17.40, Djordje Todorovic wrote:
> Add functional test for RISC-V big-endian.
> 
> Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com>
> ---
>   tests/functional/riscv64/meson.build       |  1 +
>   tests/functional/riscv64/test_bigendian.py | 57 ++++++++++++++++++++++
>   2 files changed, 58 insertions(+)
>   create mode 100644 tests/functional/riscv64/test_bigendian.py
> 
> diff --git a/tests/functional/riscv64/meson.build b/tests/functional/riscv64/meson.build
> index b996c89d7d..d06d6ea112 100644
> --- a/tests/functional/riscv64/meson.build
> +++ b/tests/functional/riscv64/meson.build
> @@ -11,6 +11,7 @@ tests_riscv64_system_quick = [
>   ]
>   
>   tests_riscv64_system_thorough = [
> +  'bigendian',
>     'boston',
>     'sifive_u',
>     'tuxrun',
> diff --git a/tests/functional/riscv64/test_bigendian.py b/tests/functional/riscv64/test_bigendian.py
> new file mode 100644
> index 0000000000..9e0b3b7db5
> --- /dev/null
> +++ b/tests/functional/riscv64/test_bigendian.py
> @@ -0,0 +1,57 @@
> +#!/usr/bin/env python3
> +#
> +# Functional tests for RISC-V big-endian support
> +#
> +# Copyright (c) 2026 MIPS
> +#
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +
> +from qemu_test import QemuSystemTest, Asset
> +from qemu_test import wait_for_console_pattern
> +
> +
> +class RiscvBigEndian(QemuSystemTest):
> +    """
> +    Tests for RISC-V runtime big-endian data support.
> +
> +    Uses a bare-metal RV64 ELF that detects data endianness at runtime
> +    by storing a 32-bit word and reading back byte 0. Prints "ENDIAN: BE"
> +    or "ENDIAN: LE" to the NS16550A UART on the virt machine.
> +    """
> +
> +    timeout = 10
> +
> +    ASSET_BE_TEST = Asset(
> +        'https://github.com/MIPS/linux-test-downloads/raw/main/'
> +        'riscvbe-baremetal/be-test-bare-metal.elf',
> +        '9ad51b675e101de65908fadbac064ed1d0564c17463715d09dd734db86ea0f58')
> +
> +    def _run_bare_metal(self, big_endian=False):
> +        self.set_machine('virt')
> +        kernel = self.ASSET_BE_TEST.fetch()
> +        self.vm.add_args('-bios', 'none')
> +        self.vm.add_args('-kernel', kernel)
> +        if big_endian:
> +            self.vm.add_args('-cpu', 'rv64,big-endian=on')
> +        self.vm.set_console()
> +        self.vm.launch()
> +        expected = 'ENDIAN: BE' if big_endian else 'ENDIAN: LE'
> +        wait_for_console_pattern(self, expected)
> +
> +    def test_bare_metal_littleendian(self):
> +        """
> +        Boot bare-metal ELF on virt with default little-endian CPU.
> +        Expects "ENDIAN: LE" on UART.
> +        """
> +        self._run_bare_metal(big_endian=False)
> +
> +    def test_bare_metal_bigendian(self):
> +        """
> +        Boot bare-metal ELF on virt with big-endian=on CPU property.
> +        Expects "ENDIAN: BE" on UART.
> +        """
> +        self._run_bare_metal(big_endian=True)
> +
> +
> +if __name__ == '__main__':
> +    QemuSystemTest.main()

Thanks for adding this!

Reviewed-by: Thomas Huth <thuth@redhat.com>



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-03-25 10:51 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-24 16:40 [PATCH v5 0/7] Add RISC-V big-endian target support Djordje Todorovic
2026-03-24 16:40 ` [PATCH v5 2/7] target/riscv: Set endianness MSTATUS bits at CPU reset Djordje Todorovic
2026-03-24 16:40 ` [PATCH v5 1/7] target/riscv: Add big-endian CPU property Djordje Todorovic
2026-03-25  7:26   ` Chao Liu
2026-03-25 10:47   ` Thomas Huth
2026-03-24 16:40 ` [PATCH v5 5/7] target/riscv: Fix page table walk endianness for big-endian harts Djordje Todorovic
2026-03-24 16:40 ` [PATCH v5 3/7] target/riscv: Implement runtime data endianness via MSTATUS bits Djordje Todorovic
2026-03-24 16:40 ` [PATCH v5 4/7] hw/riscv: Make boot code endianness-aware at runtime Djordje Todorovic
2026-03-24 16:40 ` [PATCH v5 6/7] target/riscv: Support runtime endianness in virtio via sysemu callback Djordje Todorovic
2026-03-24 16:40 ` [PATCH v5 7/7] target/riscv: Add test for RISC-V BE Djordje Todorovic
2026-03-25 10:51   ` Thomas Huth
2026-03-25  3:58 ` [PATCH v5 0/7] Add RISC-V big-endian target support Chao Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox