public inbox for qemu-devel@nongnu.org
 help / color / mirror / Atom feed
* [PATCH v3 0/9] Add RISC-V big-endian target support
@ 2026-03-11 11:59 Djordje Todorovic
  2026-03-11 11:59 ` [PATCH v3 3/9] target/riscv: Add big-endian CPU property Djordje Todorovic
                   ` (8 more replies)
  0 siblings, 9 replies; 19+ messages in thread
From: Djordje Todorovic @ 2026-03-11 11:59 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

- Address comments from reviewers
- Handle both endianness within signle binary
- Rebase on top of main branch

Djordje Todorovic (9):
  target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks
  target/riscv: Use MO_LE for instruction fetch
  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
  system/memory: Fix subpage endianness for big-endian targets
  hw/virtio: Support runtime endianness in virtio access helpers

 hw/riscv/boot.c                   | 68 +++++++++++++++++++++++++------
 include/hw/riscv/boot.h           |  2 +
 include/hw/virtio/virtio-access.h |  6 ++-
 include/qemu/target-info.h        |  9 ++++
 system/physmem.c                  |  2 +-
 target-info-stub.c                |  8 +++-
 target/riscv/cpu.c                | 16 +++++---
 target/riscv/cpu.h                | 24 +++++++++++
 target/riscv/cpu_bits.h           |  2 +
 target/riscv/cpu_cfg_fields.h.inc |  1 +
 target/riscv/cpu_helper.c         | 26 +++++++++---
 target/riscv/op_helper.c          |  9 +---
 target/riscv/tcg/tcg-cpu.c        |  9 +++-
 target/riscv/translate.c          | 20 ++++-----
 14 files changed, 155 insertions(+), 47 deletions(-)

-- 
2.34.1


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

* [PATCH v3 1/9] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks
  2026-03-11 11:59 [PATCH v3 0/9] Add RISC-V big-endian target support Djordje Todorovic
  2026-03-11 11:59 ` [PATCH v3 3/9] target/riscv: Add big-endian CPU property Djordje Todorovic
@ 2026-03-11 11:59 ` Djordje Todorovic
  2026-03-11 12:06   ` Philippe Mathieu-Daudé
  2026-03-12  0:27   ` Alistair Francis
  2026-03-11 11:59 ` [PATCH v3 2/9] target/riscv: Use MO_LE for instruction fetch Djordje Todorovic
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 19+ messages in thread
From: Djordje Todorovic @ 2026-03-11 11:59 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 the RISC-V privileged ISA defined bit positions for the Supervisor
Big-Endian (SBE, bit 36) and Machine Big-Endian (MBE, bit 37) fields
in the mstatus register. These are used alongside the existing
MSTATUS_UBE (bit 6) to control data endianness at each privilege level.

The MSTATUS_UBE definition was already present, but SBE and MBE were
missing.
---
 target/riscv/cpu_bits.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index b62dd82fe7..c2a3ee4bf3 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -628,6 +628,8 @@
 #define MSTATUS_TSR         0x00400000 /* since: priv-1.10 */
 #define MSTATUS_SPELP       0x00800000 /* zicfilp */
 #define MSTATUS_SDT         0x01000000
+#define MSTATUS_SBE         0x1000000000ULL
+#define MSTATUS_MBE         0x2000000000ULL
 #define MSTATUS_MPELP       0x020000000000 /* zicfilp */
 #define MSTATUS_GVA         0x4000000000ULL
 #define MSTATUS_MPV         0x8000000000ULL
-- 
2.34.1


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

* [PATCH v3 2/9] target/riscv: Use MO_LE for instruction fetch
  2026-03-11 11:59 [PATCH v3 0/9] Add RISC-V big-endian target support Djordje Todorovic
  2026-03-11 11:59 ` [PATCH v3 3/9] target/riscv: Add big-endian CPU property Djordje Todorovic
  2026-03-11 11:59 ` [PATCH v3 1/9] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks Djordje Todorovic
@ 2026-03-11 11:59 ` Djordje Todorovic
  2026-03-12  0:27   ` Alistair Francis
  2026-03-11 11:59 ` [PATCH v3 5/9] target/riscv: Implement runtime data endianness via MSTATUS bits Djordje Todorovic
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Djordje Todorovic @ 2026-03-11 11:59 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

RISC-V instructions are always little-endian regardless of the data
endianness mode configured via mstatus SBE/MBE/UBE bits.

Currently, instruction fetches in decode_opc() and the page boundary
check use mo_endian(ctx), which returns MO_TE. This happens to work
today because RISC-V targets are little-endian only, but is
semantically incorrect and will break once mo_endian() is updated to
respect runtime data endianness for big-endian support.

Use MO_LE explicitly for all instruction fetch paths. Data memory
operations (AMOs, loads/stores via mxl_memop) continue to use
mo_endian(ctx) as they should respect the configured data endianness.
---
 target/riscv/translate.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index cb4f443601..413911f7f9 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1255,7 +1255,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx)
          * additional page fault.
          */
         opcode = translator_ldl_end(env, &ctx->base, ctx->base.pc_next,
-                                    mo_endian(ctx));
+                                    MO_LE);
     } else {
         /*
          * For unaligned pc, instruction preload may trigger additional
@@ -1263,7 +1263,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx)
          */
         opcode = (uint32_t) translator_lduw_end(env, &ctx->base,
                                                 ctx->base.pc_next,
-                                                mo_endian(ctx));
+                                                MO_LE);
     }
     ctx->ol = ctx->xl;
 
@@ -1285,7 +1285,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx)
             opcode = deposit32(opcode, 16, 16,
                                translator_lduw_end(env, &ctx->base,
                                                    ctx->base.pc_next + 2,
-                                                   mo_endian(ctx)));
+                                                   MO_LE));
         }
         ctx->opcode = opcode;
 
@@ -1401,7 +1401,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
             if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
                 uint16_t next_insn =
                     translator_lduw_end(env, &ctx->base, ctx->base.pc_next,
-                                        mo_endian(ctx));
+                                        MO_LE);
                 int len = insn_len(next_insn);
 
                 if (!translator_is_same_page(&ctx->base, ctx->base.pc_next + len - 1)) {
-- 
2.34.1


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

* [PATCH v3 3/9] target/riscv: Add big-endian CPU property
  2026-03-11 11:59 [PATCH v3 0/9] Add RISC-V big-endian target support Djordje Todorovic
@ 2026-03-11 11:59 ` Djordje Todorovic
  2026-03-11 12:09   ` Philippe Mathieu-Daudé
  2026-03-11 11:59 ` [PATCH v3 1/9] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks Djordje Todorovic
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Djordje Todorovic @ 2026-03-11 11:59 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.
---
 include/qemu/target-info.h        | 9 +++++++++
 target-info-stub.c                | 8 +++++++-
 target/riscv/cpu.c                | 6 ++++++
 target/riscv/cpu_cfg_fields.h.inc | 1 +
 4 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h
index 23c997de54..1701cc1c9d 100644
--- a/include/qemu/target-info.h
+++ b/include/qemu/target-info.h
@@ -50,6 +50,15 @@ const char *target_cpu_type(void);
  */
 bool target_big_endian(void);
 
+/**
+ * target_set_big_endian:
+ * @big_endian: the new endianness setting
+ *
+ * Set the target endianness at runtime. Used by bi-endian targets
+ * (e.g. RISC-V) where data endianness is a runtime CPU property.
+ */
+void target_set_big_endian(bool big_endian);
+
 /**
  * target_base_arm:
  *
diff --git a/target-info-stub.c b/target-info-stub.c
index f5896a7262..b6532c419a 100644
--- a/target-info-stub.c
+++ b/target-info-stub.c
@@ -22,7 +22,7 @@ QEMU_BUILD_BUG_ON(offsetof(ArchCPU, env) != sizeof(CPUState));
 QEMU_BUILD_BUG_ON(TARGET_PAGE_BITS < TARGET_PAGE_BITS_MIN);
 #endif
 
-static const TargetInfo target_info_stub = {
+static TargetInfo target_info_stub = {
     .target_name = TARGET_NAME,
     .target_arch = glue(SYS_EMU_TARGET_, TARGET_ARCH),
     .long_bits = TARGET_LONG_BITS,
@@ -44,3 +44,9 @@ const TargetInfo *target_info(void)
 {
     return &target_info_stub;
 }
+
+void target_set_big_endian(bool big_endian)
+{
+    target_info_stub.endianness = big_endian
+        ? ENDIAN_MODE_BIG : ENDIAN_MODE_LITTLE;
+}
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e56470a374..305a8d73ad 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -34,6 +34,7 @@
 #include "system/device_tree.h"
 #include "system/kvm.h"
 #include "system/tcg.h"
+#include "qemu/target-info.h"
 #include "kvm/kvm_riscv.h"
 #include "tcg/tcg-cpu.h"
 #include "tcg/tcg.h"
@@ -941,6 +942,10 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    if (cpu->cfg.big_endian) {
+        target_set_big_endian(true);
+    }
+
     riscv_cpu_register_gdb_regs_for_features(cs);
 
 #ifndef CONFIG_USER_ONLY
@@ -2641,6 +2646,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] 19+ messages in thread

* [PATCH v3 5/9] target/riscv: Implement runtime data endianness via MSTATUS bits
  2026-03-11 11:59 [PATCH v3 0/9] Add RISC-V big-endian target support Djordje Todorovic
                   ` (2 preceding siblings ...)
  2026-03-11 11:59 ` [PATCH v3 2/9] target/riscv: Use MO_LE for instruction fetch Djordje Todorovic
@ 2026-03-11 11:59 ` Djordje Todorovic
  2026-03-11 11:59 ` [PATCH v3 4/9] target/riscv: Set endianness MSTATUS bits at CPU reset Djordje Todorovic
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: Djordje Todorovic @ 2026-03-11 11:59 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.
---
 target/riscv/cpu.h         | 24 ++++++++++++++++++++++++
 target/riscv/op_helper.c   |  9 +--------
 target/riscv/tcg/tcg-cpu.c |  9 ++++++++-
 target/riscv/translate.c   | 12 ++++--------
 4 files changed, 37 insertions(+), 17 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 35d1f6362c..c644462dfa 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
@@ -729,6 +735,24 @@ static inline int cpu_address_mode(CPURISCVState *env)
     return mode;
 }
 
+/*
+ * 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)
+{
+    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();
+    }
+}
+
 static inline RISCVMXL cpu_get_xl(CPURISCVState *env, target_ulong mode)
 {
     RISCVMXL xl = env->misa_mxl;
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 6ccc127c30..18f7773a38 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -31,14 +31,7 @@
 #ifndef CONFIG_USER_ONLY
 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_TE;
+    return riscv_cpu_data_is_big_endian(env) ? MO_BE : MO_LE;
 }
 #endif
 
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 988b2d905f..e0f8fa2734 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 413911f7f9..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_TE;
+    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] 19+ messages in thread

* [PATCH v3 4/9] target/riscv: Set endianness MSTATUS bits at CPU reset
  2026-03-11 11:59 [PATCH v3 0/9] Add RISC-V big-endian target support Djordje Todorovic
                   ` (3 preceding siblings ...)
  2026-03-11 11:59 ` [PATCH v3 5/9] target/riscv: Implement runtime data endianness via MSTATUS bits Djordje Todorovic
@ 2026-03-11 11:59 ` Djordje Todorovic
  2026-03-11 11:59 ` [PATCH v3 7/9] target/riscv: Fix page table walk endianness for big-endian harts Djordje Todorovic
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: Djordje Todorovic @ 2026-03-11 11:59 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.
---
 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 305a8d73ad..4e5781ff04 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -717,6 +717,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;
@@ -804,11 +807,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] 19+ messages in thread

* [PATCH v3 8/9] system/memory: Fix subpage endianness for big-endian targets
  2026-03-11 11:59 [PATCH v3 0/9] Add RISC-V big-endian target support Djordje Todorovic
                   ` (5 preceding siblings ...)
  2026-03-11 11:59 ` [PATCH v3 7/9] target/riscv: Fix page table walk endianness for big-endian harts Djordje Todorovic
@ 2026-03-11 11:59 ` Djordje Todorovic
  2026-03-11 12:19   ` Philippe Mathieu-Daudé
  2026-03-11 11:59 ` [PATCH v3 6/9] hw/riscv: Make boot code endianness-aware at runtime Djordje Todorovic
  2026-03-11 11:59 ` [PATCH v3 9/9] hw/virtio: Support runtime endianness in virtio access helpers Djordje Todorovic
  8 siblings, 1 reply; 19+ messages in thread
From: Djordje Todorovic @ 2026-03-11 11:59 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 subpage memory region wrapper dispatches MMIO accesses through
flatview_read/write, which re-enters memory_region_dispatch_read/write
on the underlying device MR. The inner dispatch uses size_memop() which
strips endianness bits (effectively MO_LE), causing adjust_endianness to
apply a byte-swap for DEVICE_NATIVE_ENDIAN devices on big-endian targets.
The outer dispatch's adjust_endianness then sees matching endianness
(MO_BE == devend_BE) and does nothing, leaving the data incorrectly swapped.

Fix by changing subpage_ops from DEVICE_NATIVE_ENDIAN to DEVICE_LITTLE_ENDIAN.
This matches the implicit LE semantics of size_memop() used in the inner
dispatch, so the outer adjust_endianness correctly compensates with a
second swap, yielding the correct net result.

For little-endian targets, DEVICE_NATIVE_ENDIAN already equals LE, so
this change has zero behavioral impact.
---
 system/physmem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/system/physmem.c b/system/physmem.c
index 2fb0c25c93..5d917482eb 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2929,7 +2929,7 @@ static const MemoryRegionOps subpage_ops = {
     .valid.min_access_size = 1,
     .valid.max_access_size = 8,
     .valid.accepts = subpage_accepts,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static int subpage_register(subpage_t *mmio, uint32_t start, uint32_t end,
-- 
2.34.1


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

* [PATCH v3 7/9] target/riscv: Fix page table walk endianness for big-endian harts
  2026-03-11 11:59 [PATCH v3 0/9] Add RISC-V big-endian target support Djordje Todorovic
                   ` (4 preceding siblings ...)
  2026-03-11 11:59 ` [PATCH v3 4/9] target/riscv: Set endianness MSTATUS bits at CPU reset Djordje Todorovic
@ 2026-03-11 11:59 ` Djordje Todorovic
  2026-03-11 12:18   ` Philippe Mathieu-Daudé
  2026-03-11 11:59 ` [PATCH v3 8/9] system/memory: Fix subpage endianness for big-endian targets Djordje Todorovic
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Djordje Todorovic @ 2026-03-11 11:59 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.
---
 target/riscv/cpu_helper.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index dd6c861a90..052ec19b23 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(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(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) {
@@ -1567,11 +1571,21 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
             target_ulong *pte_pa = qemu_map_ram_ptr(mr->ram_block, addr1);
             target_ulong old_pte;
             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);
+                if (riscv_cpu_data_is_big_endian(env)) {
+                    old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, cpu_to_be32(pte), cpu_to_be32(updated_pte));
+                    old_pte = be32_to_cpu(old_pte);
+                } else {
+                    old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, cpu_to_le32(pte), cpu_to_le32(updated_pte));
+                    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);
+                if (riscv_cpu_data_is_big_endian(env)) {
+                    old_pte = qatomic_cmpxchg(pte_pa, cpu_to_be64(pte), cpu_to_be64(updated_pte));
+                    old_pte = be64_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);
+                }
             }
             if (old_pte != pte) {
                 goto restart;
-- 
2.34.1


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

* [PATCH v3 6/9] hw/riscv: Make boot code endianness-aware at runtime
  2026-03-11 11:59 [PATCH v3 0/9] Add RISC-V big-endian target support Djordje Todorovic
                   ` (6 preceding siblings ...)
  2026-03-11 11:59 ` [PATCH v3 8/9] system/memory: Fix subpage endianness for big-endian targets Djordje Todorovic
@ 2026-03-11 11:59 ` Djordje Todorovic
  2026-03-11 12:16   ` Philippe Mathieu-Daudé
  2026-03-11 11:59 ` [PATCH v3 9/9] hw/virtio: Support runtime endianness in virtio access helpers Djordje Todorovic
  8 siblings, 1 reply; 19+ messages in thread
From: Djordje Todorovic @ 2026-03-11 11:59 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.
---
 hw/riscv/boot.c         | 68 +++++++++++++++++++++++++++++++++--------
 include/hw/riscv/boot.h |  2 ++
 2 files changed, 58 insertions(+), 12 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index e5490beda0..e9a049d2ba 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -40,6 +40,11 @@ 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;
+}
+
 /*
  * Return the per-socket PLIC hart topology configuration string
  * (caller must free with g_free())
@@ -72,6 +77,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 +253,10 @@ 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,
+                                   info->is_big_endian ? ELFDATA2MSB
+                                                       : ELFDATA2LSB,
+                                   EM_RISCV, 1, 0, NULL, true, sym_cb);
     if (kernel_size > 0) {
         info->kernel_size = kernel_size;
         goto out;
@@ -391,21 +399,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 +493,35 @@ 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. For 64-bit big-endian, the high/low word order within
+     * each dword must also be swapped since LD interprets bytes as BE.
+     */
+    if (riscv_is_big_endian(harts)) {
+        if (!riscv_is_32bit(harts)) {
+            uint32_t tmp;
+            tmp = reset_vec[6];
+            reset_vec[6] = cpu_to_be32(reset_vec[7]);
+            reset_vec[7] = cpu_to_be32(tmp);
+            tmp = reset_vec[8];
+            reset_vec[8] = cpu_to_be32(reset_vec[9]);
+            reset_vec[9] = cpu_to_be32(tmp);
+        } else {
+            for (i = 6; i < ARRAY_SIZE(reset_vec); i++) {
+                reset_vec[i] = cpu_to_be32(reset_vec[i]);
+            }
+        }
+    } else {
+        for (i = 6; i < ARRAY_SIZE(reset_vec); i++) {
+            reset_vec[i] = cpu_to_le32(reset_vec[i]);
+        }
+    }
     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] 19+ messages in thread

* [PATCH v3 9/9] hw/virtio: Support runtime endianness in virtio access helpers
  2026-03-11 11:59 [PATCH v3 0/9] Add RISC-V big-endian target support Djordje Todorovic
                   ` (7 preceding siblings ...)
  2026-03-11 11:59 ` [PATCH v3 6/9] hw/riscv: Make boot code endianness-aware at runtime Djordje Todorovic
@ 2026-03-11 11:59 ` Djordje Todorovic
  2026-03-11 12:21   ` Philippe Mathieu-Daudé
  8 siblings, 1 reply; 19+ messages in thread
From: Djordje Todorovic @ 2026-03-11 11:59 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

For targets compiled as little-endian but supporting runtime big-endian
mode (e.g. RISC-V with big-endian=true), virtio_access_is_big_endian()
unconditionally returned false. This caused legacy virtio config space
values to be stored in LE byte order even when the guest runs in BE mode,
leading to byte-swapped config reads (e.g. virtio-blk block size 512
read as 131072).

Use target_big_endian() in the #else branch to detect runtime endianness.
For LE targets that are truly LE, target_big_endian() returns false so
behavior is unchanged. For bi-endian targets running in BE mode, config
values are now correctly stored in BE byte order, matching what the
guest's le32_to_cpu() conversion expects.
---
 include/hw/virtio/virtio-access.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h
index b58fb6ed7e..a3f1b9f5fe 100644
--- a/include/hw/virtio/virtio-access.h
+++ b/include/hw/virtio/virtio-access.h
@@ -20,6 +20,7 @@
 #include "system/memory_cached.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-bus.h"
+#include "qemu/target-info.h"
 
 #if defined(TARGET_PPC64) || defined(TARGET_ARM)
 #define LEGACY_VIRTIO_IS_BIENDIAN 1
@@ -36,7 +37,10 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
     }
     return true;
 #else
-    return false;
+    if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+        return false;
+    }
+    return target_big_endian();
 #endif
 }
 
-- 
2.34.1


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

* Re: [PATCH v3 1/9] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks
  2026-03-11 11:59 ` [PATCH v3 1/9] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks Djordje Todorovic
@ 2026-03-11 12:06   ` Philippe Mathieu-Daudé
  2026-03-12  0:27   ` Alistair Francis
  1 sibling, 0 replies; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-11 12:06 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,
	alistair23@gmail.com, thuth@redhat.com

On 11/3/26 12:59, Djordje Todorovic wrote:
> Add the RISC-V privileged ISA defined bit positions for the Supervisor
> Big-Endian (SBE, bit 36) and Machine Big-Endian (MBE, bit 37) fields
> in the mstatus register. These are used alongside the existing
> MSTATUS_UBE (bit 6) to control data endianness at each privilege level.
> 
> The MSTATUS_UBE definition was already present, but SBE and MBE were
> missing.
> ---
>   target/riscv/cpu_bits.h | 2 ++
>   1 file changed, 2 insertions(+)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>


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

* Re: [PATCH v3 3/9] target/riscv: Add big-endian CPU property
  2026-03-11 11:59 ` [PATCH v3 3/9] target/riscv: Add big-endian CPU property Djordje Todorovic
@ 2026-03-11 12:09   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-11 12:09 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,
	alistair23@gmail.com, thuth@redhat.com, Pierrick Bouvier

On 11/3/26 12:59, 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.
> ---
>   include/qemu/target-info.h        | 9 +++++++++
>   target-info-stub.c                | 8 +++++++-
>   target/riscv/cpu.c                | 6 ++++++
>   target/riscv/cpu_cfg_fields.h.inc | 1 +
>   4 files changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h
> index 23c997de54..1701cc1c9d 100644
> --- a/include/qemu/target-info.h
> +++ b/include/qemu/target-info.h
> @@ -50,6 +50,15 @@ const char *target_cpu_type(void);
>    */
>   bool target_big_endian(void);
>   
> +/**
> + * target_set_big_endian:
> + * @big_endian: the new endianness setting
> + *
> + * Set the target endianness at runtime. Used by bi-endian targets
> + * (e.g. RISC-V) where data endianness is a runtime CPU property.
> + */
> +void target_set_big_endian(bool big_endian);
> +
>   /**
>    * target_base_arm:
>    *
> diff --git a/target-info-stub.c b/target-info-stub.c
> index f5896a7262..b6532c419a 100644
> --- a/target-info-stub.c
> +++ b/target-info-stub.c
> @@ -22,7 +22,7 @@ QEMU_BUILD_BUG_ON(offsetof(ArchCPU, env) != sizeof(CPUState));
>   QEMU_BUILD_BUG_ON(TARGET_PAGE_BITS < TARGET_PAGE_BITS_MIN);
>   #endif
>   
> -static const TargetInfo target_info_stub = {
> +static TargetInfo target_info_stub = {

NAck. This structure must stay const. (this change isn't even
documented / justified).

What is the problem you are trying to resolve here?

>       .target_name = TARGET_NAME,
>       .target_arch = glue(SYS_EMU_TARGET_, TARGET_ARCH),
>       .long_bits = TARGET_LONG_BITS,
> @@ -44,3 +44,9 @@ const TargetInfo *target_info(void)
>   {
>       return &target_info_stub;
>   }
> +
> +void target_set_big_endian(bool big_endian)
> +{
> +    target_info_stub.endianness = big_endian
> +        ? ENDIAN_MODE_BIG : ENDIAN_MODE_LITTLE;
> +}
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index e56470a374..305a8d73ad 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -34,6 +34,7 @@
>   #include "system/device_tree.h"
>   #include "system/kvm.h"
>   #include "system/tcg.h"
> +#include "qemu/target-info.h"
>   #include "kvm/kvm_riscv.h"
>   #include "tcg/tcg-cpu.h"
>   #include "tcg/tcg.h"
> @@ -941,6 +942,10 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
>           return;
>       }
>   
> +    if (cpu->cfg.big_endian) {
> +        target_set_big_endian(true);
> +    }
> +
>       riscv_cpu_register_gdb_regs_for_features(cs);
>   
>   #ifndef CONFIG_USER_ONLY
> @@ -2641,6 +2646,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)



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

* Re: [PATCH v3 6/9] hw/riscv: Make boot code endianness-aware at runtime
  2026-03-11 11:59 ` [PATCH v3 6/9] hw/riscv: Make boot code endianness-aware at runtime Djordje Todorovic
@ 2026-03-11 12:16   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-11 12:16 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,
	alistair23@gmail.com, thuth@redhat.com

On 11/3/26 12:59, Djordje Todorovic wrote:
> 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.
> ---
>   hw/riscv/boot.c         | 68 +++++++++++++++++++++++++++++++++--------
>   include/hw/riscv/boot.h |  2 ++
>   2 files changed, 58 insertions(+), 12 deletions(-)


> @@ -474,10 +493,35 @@ 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. For 64-bit big-endian, the high/low word order within
> +     * each dword must also be swapped since LD interprets bytes as BE.
> +     */
> +    if (riscv_is_big_endian(harts)) {

Do not consider endianness as an exceptional case. Please re-order
as:

        for(...) {
           if (32bit) {
               if (big_endian) {

Even clearer if you add a riscv_boot_swap_data64() helper:

       for(...) {
           riscv_boot_swap_data64();
       }

> +        if (!riscv_is_32bit(harts)) {
> +            uint32_t tmp;
> +            tmp = reset_vec[6];
> +            reset_vec[6] = cpu_to_be32(reset_vec[7]);
> +            reset_vec[7] = cpu_to_be32(tmp);
> +            tmp = reset_vec[8];
> +            reset_vec[8] = cpu_to_be32(reset_vec[9]);
> +            reset_vec[9] = cpu_to_be32(tmp);
> +        } else {
> +            for (i = 6; i < ARRAY_SIZE(reset_vec); i++) {
> +                reset_vec[i] = cpu_to_be32(reset_vec[i]);
> +            }
> +        }
> +    } else {
> +        for (i = 6; i < ARRAY_SIZE(reset_vec); i++) {
> +            reset_vec[i] = cpu_to_le32(reset_vec[i]);
> +        }
> +    }


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

* Re: [PATCH v3 7/9] target/riscv: Fix page table walk endianness for big-endian harts
  2026-03-11 11:59 ` [PATCH v3 7/9] target/riscv: Fix page table walk endianness for big-endian harts Djordje Todorovic
@ 2026-03-11 12:18   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-11 12:18 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,
	alistair23@gmail.com, thuth@redhat.com

On 11/3/26 12:59, Djordje Todorovic wrote:
> 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.
> ---
>   target/riscv/cpu_helper.c | 26 ++++++++++++++++++++------
>   1 file changed, 20 insertions(+), 6 deletions(-)


> @@ -1567,11 +1571,21 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
>               target_ulong *pte_pa = qemu_map_ram_ptr(mr->ram_block, addr1);
>               target_ulong old_pte;
>               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);
> +                if (riscv_cpu_data_is_big_endian(env)) {
> +                    old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, cpu_to_be32(pte), cpu_to_be32(updated_pte));
> +                    old_pte = be32_to_cpu(old_pte);
> +                } else {
> +                    old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, cpu_to_le32(pte), cpu_to_le32(updated_pte));
> +                    old_pte = le32_to_cpu(old_pte);
> +                }

I expect checkpatch.pl script to complain for long lines, otherwise:

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH v3 8/9] system/memory: Fix subpage endianness for big-endian targets
  2026-03-11 11:59 ` [PATCH v3 8/9] system/memory: Fix subpage endianness for big-endian targets Djordje Todorovic
@ 2026-03-11 12:19   ` Philippe Mathieu-Daudé
  2026-03-18  7:00     ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-11 12:19 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,
	alistair23@gmail.com, thuth@redhat.com

On 11/3/26 12:59, Djordje Todorovic wrote:
> The subpage memory region wrapper dispatches MMIO accesses through
> flatview_read/write, which re-enters memory_region_dispatch_read/write
> on the underlying device MR. The inner dispatch uses size_memop() which
> strips endianness bits (effectively MO_LE), causing adjust_endianness to
> apply a byte-swap for DEVICE_NATIVE_ENDIAN devices on big-endian targets.
> The outer dispatch's adjust_endianness then sees matching endianness
> (MO_BE == devend_BE) and does nothing, leaving the data incorrectly swapped.
> 
> Fix by changing subpage_ops from DEVICE_NATIVE_ENDIAN to DEVICE_LITTLE_ENDIAN.
> This matches the implicit LE semantics of size_memop() used in the inner
> dispatch, so the outer adjust_endianness correctly compensates with a
> second swap, yielding the correct net result.
> 
> For little-endian targets, DEVICE_NATIVE_ENDIAN already equals LE, so
> this change has zero behavioral impact.
> ---
>   system/physmem.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/system/physmem.c b/system/physmem.c
> index 2fb0c25c93..5d917482eb 100644
> --- a/system/physmem.c
> +++ b/system/physmem.c
> @@ -2929,7 +2929,7 @@ static const MemoryRegionOps subpage_ops = {
>       .valid.min_access_size = 1,
>       .valid.max_access_size = 8,
>       .valid.accepts = subpage_accepts,
> -    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .endianness = DEVICE_LITTLE_ENDIAN,

NAck, this likely break big-endian hosts.

>   };



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

* Re: [PATCH v3 9/9] hw/virtio: Support runtime endianness in virtio access helpers
  2026-03-11 11:59 ` [PATCH v3 9/9] hw/virtio: Support runtime endianness in virtio access helpers Djordje Todorovic
@ 2026-03-11 12:21   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-11 12:21 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,
	alistair23@gmail.com, thuth@redhat.com

On 11/3/26 12:59, Djordje Todorovic wrote:
> For targets compiled as little-endian but supporting runtime big-endian
> mode (e.g. RISC-V with big-endian=true), virtio_access_is_big_endian()
> unconditionally returned false. This caused legacy virtio config space
> values to be stored in LE byte order even when the guest runs in BE mode,
> leading to byte-swapped config reads (e.g. virtio-blk block size 512
> read as 131072).
> 
> Use target_big_endian() in the #else branch to detect runtime endianness.
> For LE targets that are truly LE, target_big_endian() returns false so
> behavior is unchanged. For bi-endian targets running in BE mode, config
> values are now correctly stored in BE byte order, matching what the
> guest's le32_to_cpu() conversion expects.
> ---
>   include/hw/virtio/virtio-access.h | 6 +++++-
>   1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h
> index b58fb6ed7e..a3f1b9f5fe 100644
> --- a/include/hw/virtio/virtio-access.h
> +++ b/include/hw/virtio/virtio-access.h
> @@ -20,6 +20,7 @@
>   #include "system/memory_cached.h"
>   #include "hw/virtio/virtio.h"
>   #include "hw/virtio/virtio-bus.h"
> +#include "qemu/target-info.h"
>   
>   #if defined(TARGET_PPC64) || defined(TARGET_ARM)
>   #define LEGACY_VIRTIO_IS_BIENDIAN 1
> @@ -36,7 +37,10 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
>       }
>       return true;
>   #else
> -    return false;
> +    if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
> +        return false;
> +    }
> +    return target_big_endian();
>   #endif
>   }

See commit 93b32a87377 and around, and please rebase your series on
current /master.


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

* Re: [PATCH v3 1/9] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks
  2026-03-11 11:59 ` [PATCH v3 1/9] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks Djordje Todorovic
  2026-03-11 12:06   ` Philippe Mathieu-Daudé
@ 2026-03-12  0:27   ` Alistair Francis
  1 sibling, 0 replies; 19+ messages in thread
From: Alistair Francis @ 2026-03-12  0:27 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, thuth@redhat.com

On Wed, Mar 11, 2026 at 9:59 PM Djordje Todorovic
<Djordje.Todorovic@htecgroup.com> wrote:
>
> Add the RISC-V privileged ISA defined bit positions for the Supervisor
> Big-Endian (SBE, bit 36) and Machine Big-Endian (MBE, bit 37) fields
> in the mstatus register. These are used alongside the existing
> MSTATUS_UBE (bit 6) to control data endianness at each privilege level.
>
> The MSTATUS_UBE definition was already present, but SBE and MBE were
> missing.

You are missing a  Signed-off-by line.

Otherwise:

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/cpu_bits.h | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index b62dd82fe7..c2a3ee4bf3 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -628,6 +628,8 @@
>  #define MSTATUS_TSR         0x00400000 /* since: priv-1.10 */
>  #define MSTATUS_SPELP       0x00800000 /* zicfilp */
>  #define MSTATUS_SDT         0x01000000
> +#define MSTATUS_SBE         0x1000000000ULL
> +#define MSTATUS_MBE         0x2000000000ULL
>  #define MSTATUS_MPELP       0x020000000000 /* zicfilp */
>  #define MSTATUS_GVA         0x4000000000ULL
>  #define MSTATUS_MPV         0x8000000000ULL
> --
> 2.34.1


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

* Re: [PATCH v3 2/9] target/riscv: Use MO_LE for instruction fetch
  2026-03-11 11:59 ` [PATCH v3 2/9] target/riscv: Use MO_LE for instruction fetch Djordje Todorovic
@ 2026-03-12  0:27   ` Alistair Francis
  0 siblings, 0 replies; 19+ messages in thread
From: Alistair Francis @ 2026-03-12  0:27 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, thuth@redhat.com

On Wed, Mar 11, 2026 at 9:59 PM Djordje Todorovic
<Djordje.Todorovic@htecgroup.com> wrote:
>
> RISC-V instructions are always little-endian regardless of the data
> endianness mode configured via mstatus SBE/MBE/UBE bits.
>
> Currently, instruction fetches in decode_opc() and the page boundary
> check use mo_endian(ctx), which returns MO_TE. This happens to work
> today because RISC-V targets are little-endian only, but is
> semantically incorrect and will break once mo_endian() is updated to
> respect runtime data endianness for big-endian support.
>
> Use MO_LE explicitly for all instruction fetch paths. Data memory
> operations (AMOs, loads/stores via mxl_memop) continue to use
> mo_endian(ctx) as they should respect the configured data endianness.

Missing Signed-off-by

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair


> ---
>  target/riscv/translate.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index cb4f443601..413911f7f9 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -1255,7 +1255,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx)
>           * additional page fault.
>           */
>          opcode = translator_ldl_end(env, &ctx->base, ctx->base.pc_next,
> -                                    mo_endian(ctx));
> +                                    MO_LE);
>      } else {
>          /*
>           * For unaligned pc, instruction preload may trigger additional
> @@ -1263,7 +1263,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx)
>           */
>          opcode = (uint32_t) translator_lduw_end(env, &ctx->base,
>                                                  ctx->base.pc_next,
> -                                                mo_endian(ctx));
> +                                                MO_LE);
>      }
>      ctx->ol = ctx->xl;
>
> @@ -1285,7 +1285,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx)
>              opcode = deposit32(opcode, 16, 16,
>                                 translator_lduw_end(env, &ctx->base,
>                                                     ctx->base.pc_next + 2,
> -                                                   mo_endian(ctx)));
> +                                                   MO_LE));
>          }
>          ctx->opcode = opcode;
>
> @@ -1401,7 +1401,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
>              if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
>                  uint16_t next_insn =
>                      translator_lduw_end(env, &ctx->base, ctx->base.pc_next,
> -                                        mo_endian(ctx));
> +                                        MO_LE);
>                  int len = insn_len(next_insn);
>
>                  if (!translator_is_same_page(&ctx->base, ctx->base.pc_next + len - 1)) {
> --
> 2.34.1


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

* Re: [PATCH v3 8/9] system/memory: Fix subpage endianness for big-endian targets
  2026-03-11 12:19   ` Philippe Mathieu-Daudé
@ 2026-03-18  7:00     ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-18  7:00 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,
	alistair23@gmail.com, thuth@redhat.com

On 11/3/26 13:19, Philippe Mathieu-Daudé wrote:
> On 11/3/26 12:59, Djordje Todorovic wrote:
>> The subpage memory region wrapper dispatches MMIO accesses through
>> flatview_read/write, which re-enters memory_region_dispatch_read/write
>> on the underlying device MR. The inner dispatch uses size_memop() which
>> strips endianness bits (effectively MO_LE), causing adjust_endianness to
>> apply a byte-swap for DEVICE_NATIVE_ENDIAN devices on big-endian targets.
>> The outer dispatch's adjust_endianness then sees matching endianness
>> (MO_BE == devend_BE) and does nothing, leaving the data incorrectly 
>> swapped.
>>
>> Fix by changing subpage_ops from DEVICE_NATIVE_ENDIAN to 
>> DEVICE_LITTLE_ENDIAN.
>> This matches the implicit LE semantics of size_memop() used in the inner
>> dispatch, so the outer adjust_endianness correctly compensates with a
>> second swap, yielding the correct net result.
>>
>> For little-endian targets, DEVICE_NATIVE_ENDIAN already equals LE, so
>> this change has zero behavioral impact.
>> ---
>>   system/physmem.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/system/physmem.c b/system/physmem.c
>> index 2fb0c25c93..5d917482eb 100644
>> --- a/system/physmem.c
>> +++ b/system/physmem.c
>> @@ -2929,7 +2929,7 @@ static const MemoryRegionOps subpage_ops = {
>>       .valid.min_access_size = 1,
>>       .valid.max_access_size = 8,
>>       .valid.accepts = subpage_accepts,
>> -    .endianness = DEVICE_NATIVE_ENDIAN,
>> +    .endianness = DEVICE_LITTLE_ENDIAN,
> 
> NAck, this likely break big-endian hosts.

(see also 
https://lore.kernel.org/qemu-devel/20251224152210.87880-4-philmd@linaro.org/ 
and Paolo's response)

>>   };
> 



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

end of thread, other threads:[~2026-03-18  7:01 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-11 11:59 [PATCH v3 0/9] Add RISC-V big-endian target support Djordje Todorovic
2026-03-11 11:59 ` [PATCH v3 3/9] target/riscv: Add big-endian CPU property Djordje Todorovic
2026-03-11 12:09   ` Philippe Mathieu-Daudé
2026-03-11 11:59 ` [PATCH v3 1/9] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks Djordje Todorovic
2026-03-11 12:06   ` Philippe Mathieu-Daudé
2026-03-12  0:27   ` Alistair Francis
2026-03-11 11:59 ` [PATCH v3 2/9] target/riscv: Use MO_LE for instruction fetch Djordje Todorovic
2026-03-12  0:27   ` Alistair Francis
2026-03-11 11:59 ` [PATCH v3 5/9] target/riscv: Implement runtime data endianness via MSTATUS bits Djordje Todorovic
2026-03-11 11:59 ` [PATCH v3 4/9] target/riscv: Set endianness MSTATUS bits at CPU reset Djordje Todorovic
2026-03-11 11:59 ` [PATCH v3 7/9] target/riscv: Fix page table walk endianness for big-endian harts Djordje Todorovic
2026-03-11 12:18   ` Philippe Mathieu-Daudé
2026-03-11 11:59 ` [PATCH v3 8/9] system/memory: Fix subpage endianness for big-endian targets Djordje Todorovic
2026-03-11 12:19   ` Philippe Mathieu-Daudé
2026-03-18  7:00     ` Philippe Mathieu-Daudé
2026-03-11 11:59 ` [PATCH v3 6/9] hw/riscv: Make boot code endianness-aware at runtime Djordje Todorovic
2026-03-11 12:16   ` Philippe Mathieu-Daudé
2026-03-11 11:59 ` [PATCH v3 9/9] hw/virtio: Support runtime endianness in virtio access helpers Djordje Todorovic
2026-03-11 12:21   ` Philippe Mathieu-Daudé

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