* [PATCH v9 0/7] Add RISC-V big-endian target support
@ 2026-05-11 8:38 Djordje Todorovic
2026-05-11 8:38 ` [PATCH v9 2/7] target/riscv: Add big-endian CPU configuration field and reset logic Djordje Todorovic
` (8 more replies)
0 siblings, 9 replies; 14+ messages in thread
From: Djordje Todorovic @ 2026-05-11 8:38 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
Rebase on top of master.
Djordje Todorovic (7):
target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks
target/riscv: Add big-endian CPU configuration field and reset logic
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: Expose big-endian CPU property and add documentation
target/riscv: Add endianness test for RISC-V BE
docs/system/target-riscv.rst | 24 ++++++
hw/riscv/boot.c | 81 ++++++++++++++++---
include/hw/riscv/boot.h | 1 +
target/riscv/cpu.c | 11 +--
target/riscv/cpu.h | 23 ++++++
target/riscv/cpu_bits.h | 2 +
target/riscv/cpu_cfg_fields.h.inc | 1 +
target/riscv/cpu_helper.c | 28 +++++--
target/riscv/insn_trans/trans_rva.c.inc | 4 +-
target/riscv/insn_trans/trans_rvd.c.inc | 4 +-
target/riscv/insn_trans/trans_rvf.c.inc | 4 +-
target/riscv/insn_trans/trans_rvi.c.inc | 8 +-
target/riscv/insn_trans/trans_rvzacas.c.inc | 4 +-
target/riscv/insn_trans/trans_rvzalasr.c.inc | 4 +-
target/riscv/insn_trans/trans_rvzce.c.inc | 4 +-
target/riscv/insn_trans/trans_rvzfh.c.inc | 4 +-
target/riscv/insn_trans/trans_rvzicfiss.c.inc | 4 +-
target/riscv/insn_trans/trans_xmips.c.inc | 8 +-
target/riscv/insn_trans/trans_xthead.c.inc | 16 ++--
target/riscv/insn_trans/trans_zilsd.c.inc | 4 +-
target/riscv/internals.h | 9 +--
target/riscv/tcg/tcg-cpu.c | 3 +
target/riscv/translate.c | 22 ++---
tests/functional/riscv64/meson.build | 1 +
tests/functional/riscv64/test_endianness.py | 57 +++++++++++++
25 files changed, 251 insertions(+), 80 deletions(-)
create mode 100644 tests/functional/riscv64/test_endianness.py
--
2.34.1
^ permalink raw reply [flat|nested] 14+ messages in thread* [PATCH v9 2/7] target/riscv: Add big-endian CPU configuration field and reset logic 2026-05-11 8:38 [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic @ 2026-05-11 8:38 ` Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 1/7] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks Djordje Todorovic ` (7 subsequent siblings) 8 siblings, 0 replies; 14+ messages in thread From: Djordje Todorovic @ 2026-05-11 8:38 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 field to RISCVCPUConfig and wire it into the CPU reset path. When cfg.big_endian is set, riscv_cpu_reset_hold() writes 1 into the MSTATUS MBE/SBE/UBE fields using set_field(); otherwise it writes 0. This makes the reset value deterministic on both cold and warm reset. The MBE/SBE/UBE bits are not included in the writable mask of any mstatus/mstatush/sstatus CSR write path (unchanged by this series), so the value chosen at reset effectively hardwires them per section 3.1.6.5 of the RISC-V Privileged Specification. The user-facing property and documentation are added in a later patch, once the full endianness support is in place. 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 +++++----- target/riscv/cpu_cfg_fields.h.inc | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ce15a17c37..ae75019186 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -720,6 +720,9 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) env->mstatus = set_field(env->mstatus, MSTATUS_MDT, 1); } } + env->mstatus = set_field(env->mstatus, MSTATUS_MBE, cpu->cfg.big_endian); + env->mstatus = set_field(env->mstatus, MSTATUS_SBE, cpu->cfg.big_endian); + env->mstatus = set_field(env->mstatus, MSTATUS_UBE, cpu->cfg.big_endian); env->mcause = 0; env->miclaim = MIP_SGEIP; env->pc = env->resetvec; @@ -807,11 +810,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; diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc index 734fa079f2..9eb47af0a7 100644 --- a/target/riscv/cpu_cfg_fields.h.inc +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -157,6 +157,7 @@ BOOL_FIELD(ext_xmipscmov) BOOL_FIELD(ext_xmipslsp) BOOL_FIELD(ext_xlrbr) +BOOL_FIELD(big_endian) BOOL_FIELD(mmu) BOOL_FIELD(pmp) BOOL_FIELD(debug) -- 2.34.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v9 1/7] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks 2026-05-11 8:38 [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 2/7] target/riscv: Add big-endian CPU configuration field and reset logic Djordje Todorovic @ 2026-05-11 8:38 ` Djordje Todorovic 2026-05-12 2:31 ` Chao Liu 2026-05-11 8:38 ` [PATCH v9 3/7] target/riscv: Implement runtime data endianness via MSTATUS bits Djordje Todorovic ` (6 subsequent siblings) 8 siblings, 1 reply; 14+ messages in thread From: Djordje Todorovic @ 2026-05-11 8:38 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, Alistair Francis 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. Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> --- 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] 14+ messages in thread
* Re: [PATCH v9 1/7] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks 2026-05-11 8:38 ` [PATCH v9 1/7] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks Djordje Todorovic @ 2026-05-12 2:31 ` Chao Liu 0 siblings, 0 replies; 14+ messages in thread From: Chao Liu @ 2026-05-12 2:31 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, Alistair Francis On Mon, May 11, 2026 at 08:38:27AM +0000, 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. > > Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com> > Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> > Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Thanks, Chao > --- > 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] 14+ messages in thread
* [PATCH v9 3/7] target/riscv: Implement runtime data endianness via MSTATUS bits 2026-05-11 8:38 [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 2/7] target/riscv: Add big-endian CPU configuration field and reset logic Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 1/7] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks Djordje Todorovic @ 2026-05-11 8:38 ` Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 4/7] hw/riscv: Make boot code endianness-aware at runtime Djordje Todorovic ` (5 subsequent siblings) 8 siblings, 0 replies; 14+ messages in thread From: Djordje Todorovic @ 2026-05-11 8:38 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 Make data accesses honour the MSTATUS MBE/SBE/UBE endianness bits instead of being hardcoded to little-endian. A new helper, riscv_cpu_data_is_big_endian(), picks the bit corresponding to the current privilege level (MBE for M, SBE for S, UBE for U). The existing mo_endian_env() wrapper in internals.h now returns MO_BE or MO_LE based on that helper, so the hypervisor load/store helpers in op_helper.c pick up the runtime endianness automatically. On the translator side, DisasContext gains a mo_endianness field holding MO_BE or MO_LE, which the generated load/store ops OR into their MemOp. The trivial mo_endian() wrapper is dropped and call sites reference ctx->mo_endianness directly. TB_FLAGS has no free bits, so the endianness is carried into the translator through bit 32 of cs_base (alongside misa_ext in bits 0-25). This keys TBs correctly on the current data endianness. The cs_base comment in include/exec/translation-block.h is updated to document the RISC-V usage. Instruction fetches remain MO_LE unconditionally; RISC-V instructions are always little-endian per the ISA specification. Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com> --- target/riscv/cpu.h | 23 +++++++++++++++++++ target/riscv/insn_trans/trans_rva.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvd.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvf.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvi.c.inc | 8 +++---- target/riscv/insn_trans/trans_rvzacas.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvzalasr.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvzce.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvzfh.c.inc | 4 ++-- target/riscv/insn_trans/trans_rvzicfiss.c.inc | 4 ++-- target/riscv/insn_trans/trans_xmips.c.inc | 8 +++---- target/riscv/insn_trans/trans_xthead.c.inc | 16 ++++++------- target/riscv/insn_trans/trans_zilsd.c.inc | 4 ++-- target/riscv/internals.h | 9 +------- target/riscv/tcg/tcg-cpu.c | 3 +++ target/riscv/translate.c | 22 ++++++------------ 16 files changed, 68 insertions(+), 57 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 81c41e3429..1f2d0777e8 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -705,6 +705,7 @@ FIELD(TB_FLAGS, PM_SIGNEXTEND, 31, 1) FIELD(EXT_TB_FLAGS, MISA_EXT, 0, 32) FIELD(EXT_TB_FLAGS, ALTFMT, 32, 1) +FIELD(EXT_TB_FLAGS, BIG_ENDIAN, 33, 1) #ifdef TARGET_RISCV32 #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32) @@ -721,6 +722,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/insn_trans/trans_rva.c.inc b/target/riscv/insn_trans/trans_rva.c.inc index 62c0fe673d..44c1696fe4 100644 --- a/target/riscv/insn_trans/trans_rva.c.inc +++ b/target/riscv/insn_trans/trans_rva.c.inc @@ -35,7 +35,7 @@ static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGv src1; mop |= MO_ALIGN; - mop |= mo_endian(ctx); + mop |= ctx->mo_endianness; decode_save_opc(ctx, 0); src1 = get_address(ctx, a->rs1, 0); @@ -65,7 +65,7 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGLabel *l2 = gen_new_label(); mop |= MO_ALIGN; - mop |= mo_endian(ctx); + mop |= ctx->mo_endianness; decode_save_opc(ctx, 0); src1 = get_address(ctx, a->rs1, 0); diff --git a/target/riscv/insn_trans/trans_rvd.c.inc b/target/riscv/insn_trans/trans_rvd.c.inc index ffea0c2a1f..3b9a745520 100644 --- a/target/riscv/insn_trans/trans_rvd.c.inc +++ b/target/riscv/insn_trans/trans_rvd.c.inc @@ -60,7 +60,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) } else { memop |= MO_ATOM_IFALIGN; } - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; decode_save_opc(ctx, 0); addr = get_address(ctx, a->rs1, a->imm); @@ -85,7 +85,7 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a) } else { memop |= MO_ATOM_IFALIGN; } - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; decode_save_opc(ctx, 0); addr = get_address(ctx, a->rs1, a->imm); diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc index 89fb0f604a..e935523c93 100644 --- a/target/riscv/insn_trans/trans_rvf.c.inc +++ b/target/riscv/insn_trans/trans_rvf.c.inc @@ -48,7 +48,7 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } @@ -71,7 +71,7 @@ static bool trans_fsw(DisasContext *ctx, arg_fsw *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 2c82ae41a7..2de74fac3a 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -392,7 +392,7 @@ static bool gen_load_i128(DisasContext *ctx, arg_lb *a, MemOp memop) } } else { tcg_gen_qemu_ld_i128(t16, addrl, ctx->mem_idx, memop); - if (mo_endian(ctx) == MO_LE) { + if (ctx->mo_endianness == MO_LE) { tcg_gen_extr_i128_i64(tl, th, t16); } else { tcg_gen_extr_i128_i64(th, tl, t16); @@ -409,7 +409,7 @@ static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop) { bool out; - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } @@ -508,7 +508,7 @@ static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop) tcg_gen_ext_tl_i64(tl, src2l); tcg_gen_ext_tl_i64(th, src2h); - if (mo_endian(ctx) == MO_LE) { + if (ctx->mo_endianness == MO_LE) { tcg_gen_concat_i64_i128(t16, tl, th); } else { tcg_gen_concat_i64_i128(t16, th, tl); @@ -520,7 +520,7 @@ static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop) static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) { - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } diff --git a/target/riscv/insn_trans/trans_rvzacas.c.inc b/target/riscv/insn_trans/trans_rvzacas.c.inc index 8d94b83ce9..79bca1e957 100644 --- a/target/riscv/insn_trans/trans_rvzacas.c.inc +++ b/target/riscv/insn_trans/trans_rvzacas.c.inc @@ -76,7 +76,7 @@ static bool gen_cmpxchg64(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGv src1 = get_address(ctx, a->rs1, 0); TCGv_i64 src2 = get_gpr_pair(ctx, a->rs2); - mop |= mo_endian(ctx); + mop |= ctx->mo_endianness; decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); tcg_gen_atomic_cmpxchg_i64(dest, src1, dest, src2, ctx->mem_idx, mop); @@ -121,7 +121,7 @@ static bool trans_amocas_q(DisasContext *ctx, arg_amocas_q *a) TCGv_i64 desth = get_gpr(ctx, a->rd == 0 ? 0 : a->rd + 1, EXT_NONE); MemOp memop = MO_ALIGN | MO_UO; - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_concat_i64_i128(src2, src2l, src2h); tcg_gen_concat_i64_i128(dest, destl, desth); decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); diff --git a/target/riscv/insn_trans/trans_rvzalasr.c.inc b/target/riscv/insn_trans/trans_rvzalasr.c.inc index 0f307affec..79b0b2c63b 100644 --- a/target/riscv/insn_trans/trans_rvzalasr.c.inc +++ b/target/riscv/insn_trans/trans_rvzalasr.c.inc @@ -29,7 +29,7 @@ static bool gen_load_acquire(DisasContext *ctx, arg_lb_aqrl *a, MemOp memop) return false; } - memop |= MO_ALIGN | mo_endian(ctx); + memop |= MO_ALIGN | ctx->mo_endianness; memop |= (ctx->cfg_ptr->ext_zama16b) ? MO_ATOM_WITHIN16 : 0; tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, memop); @@ -79,7 +79,7 @@ static bool gen_store_release(DisasContext *ctx, arg_sb_aqrl *a, MemOp memop) return false; } - memop |= MO_ALIGN | mo_endian(ctx); + memop |= MO_ALIGN | ctx->mo_endianness; memop |= (ctx->cfg_ptr->ext_zama16b) ? MO_ATOM_WITHIN16 : 0; /* Add a memory barrier implied by RL (mandatory) and AQ (optional) */ diff --git a/target/riscv/insn_trans/trans_rvzce.c.inc b/target/riscv/insn_trans/trans_rvzce.c.inc index 0d3ba40e52..71b4ca5473 100644 --- a/target/riscv/insn_trans/trans_rvzce.c.inc +++ b/target/riscv/insn_trans/trans_rvzce.c.inc @@ -185,7 +185,7 @@ static bool gen_pop(DisasContext *ctx, arg_cmpp *a, bool ret, bool ret_val) tcg_gen_addi_tl(addr, sp, stack_adj - reg_size); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; for (i = X_Sn + 11; i >= 0; i--) { if (reg_bitmap & (1 << i)) { TCGv dest = dest_gpr(ctx, i); @@ -239,7 +239,7 @@ static bool trans_cm_push(DisasContext *ctx, arg_cm_push *a) tcg_gen_subi_tl(addr, sp, reg_size); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; for (i = X_Sn + 11; i >= 0; i--) { if (reg_bitmap & (1 << i)) { TCGv val = get_gpr(ctx, i, EXT_NONE); diff --git a/target/riscv/insn_trans/trans_rvzfh.c.inc b/target/riscv/insn_trans/trans_rvzfh.c.inc index 791ee51f65..f36b46c211 100644 --- a/target/riscv/insn_trans/trans_rvzfh.c.inc +++ b/target/riscv/insn_trans/trans_rvzfh.c.inc @@ -49,7 +49,7 @@ static bool trans_flh(DisasContext *ctx, arg_flh *a) REQUIRE_FPU; REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; decode_save_opc(ctx, 0); t0 = get_gpr(ctx, a->rs1, EXT_NONE); if (a->imm) { @@ -74,7 +74,7 @@ static bool trans_fsh(DisasContext *ctx, arg_fsh *a) REQUIRE_FPU; REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; decode_save_opc(ctx, 0); t0 = get_gpr(ctx, a->rs1, EXT_NONE); if (a->imm) { diff --git a/target/riscv/insn_trans/trans_rvzicfiss.c.inc b/target/riscv/insn_trans/trans_rvzicfiss.c.inc index 0b6ad57965..43f586dce9 100644 --- a/target/riscv/insn_trans/trans_rvzicfiss.c.inc +++ b/target/riscv/insn_trans/trans_rvzicfiss.c.inc @@ -105,7 +105,7 @@ static bool trans_ssamoswap_w(DisasContext *ctx, arg_amoswap_w *a) decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); src1 = get_address(ctx, a->rs1, 0); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx), memop); gen_set_gpr(ctx, a->rd, dest); return true; @@ -135,7 +135,7 @@ static bool trans_ssamoswap_d(DisasContext *ctx, arg_amoswap_w *a) decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); src1 = get_address(ctx, a->rs1, 0); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx), memop); gen_set_gpr(ctx, a->rd, dest); return true; diff --git a/target/riscv/insn_trans/trans_xmips.c.inc b/target/riscv/insn_trans/trans_xmips.c.inc index c1a30156d3..1b9993a9b0 100644 --- a/target/riscv/insn_trans/trans_xmips.c.inc +++ b/target/riscv/insn_trans/trans_xmips.c.inc @@ -47,7 +47,7 @@ static bool trans_ccmov(DisasContext *ctx, arg_ccmov *a) /* Load Doubleword Pair. */ static bool trans_ldp(DisasContext *ctx, arg_ldp *a) { - MemOp memop = MO_SQ | mo_endian(ctx); + MemOp memop = MO_SQ | ctx->mo_endianness; REQUIRE_XMIPSLSP(ctx); REQUIRE_64_OR_128BIT(ctx); @@ -71,7 +71,7 @@ static bool trans_ldp(DisasContext *ctx, arg_ldp *a) /* Load Word Pair. */ static bool trans_lwp(DisasContext *ctx, arg_lwp *a) { - MemOp memop = MO_SL | mo_endian(ctx); + MemOp memop = MO_SL | ctx->mo_endianness; REQUIRE_XMIPSLSP(ctx); @@ -94,7 +94,7 @@ static bool trans_lwp(DisasContext *ctx, arg_lwp *a) /* Store Doubleword Pair. */ static bool trans_sdp(DisasContext *ctx, arg_sdp *a) { - MemOp memop = MO_UQ | mo_endian(ctx); + MemOp memop = MO_UQ | ctx->mo_endianness; REQUIRE_XMIPSLSP(ctx); REQUIRE_64_OR_128BIT(ctx); @@ -116,7 +116,7 @@ static bool trans_sdp(DisasContext *ctx, arg_sdp *a) /* Store Word Pair. */ static bool trans_swp(DisasContext *ctx, arg_swp *a) { - MemOp memop = MO_SL | mo_endian(ctx); + MemOp memop = MO_SL | ctx->mo_endianness; REQUIRE_XMIPSLSP(ctx); diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc index f8b95c6498..f4e3051000 100644 --- a/target/riscv/insn_trans/trans_xthead.c.inc +++ b/target/riscv/insn_trans/trans_xthead.c.inc @@ -349,7 +349,7 @@ static bool gen_fload_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv_i64 rd = cpu_fpr[a->rd]; TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_ld_i64(rd, addr, ctx->mem_idx, memop); if ((memop & MO_SIZE) == MO_32) { gen_nanbox_s(rd, rd); @@ -370,7 +370,7 @@ static bool gen_fstore_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv_i64 rd = cpu_fpr[a->rd]; TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_st_i64(rd, addr, ctx->mem_idx, memop); return true; @@ -570,7 +570,7 @@ static bool gen_load_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop, TCGv rd = dest_gpr(ctx, a->rd); TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop); tcg_gen_addi_tl(rs1, rs1, imm); gen_set_gpr(ctx, a->rd, rd); @@ -591,7 +591,7 @@ static bool gen_store_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop, TCGv data = get_gpr(ctx, a->rd, EXT_NONE); TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop); tcg_gen_addi_tl(rs1, rs1, imm); gen_set_gpr(ctx, a->rs1, rs1); @@ -747,7 +747,7 @@ static bool gen_load_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv rd = dest_gpr(ctx, a->rd); TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop); gen_set_gpr(ctx, a->rd, rd); @@ -765,7 +765,7 @@ static bool gen_store_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv data = get_gpr(ctx, a->rd, EXT_NONE); TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop); return true; @@ -926,7 +926,7 @@ static bool gen_loadpair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop, addr1 = get_address(ctx, a->rs, imm); addr2 = get_address(ctx, a->rs, memop_size(memop) + imm); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_ld_tl(t1, addr1, ctx->mem_idx, memop); tcg_gen_qemu_ld_tl(t2, addr2, ctx->mem_idx, memop); gen_set_gpr(ctx, a->rd1, t1); @@ -965,7 +965,7 @@ static bool gen_storepair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop, addr1 = get_address(ctx, a->rs, imm); addr2 = get_address(ctx, a->rs, memop_size(memop) + imm); - memop |= mo_endian(ctx); + memop |= ctx->mo_endianness; tcg_gen_qemu_st_tl(data1, addr1, ctx->mem_idx, memop); tcg_gen_qemu_st_tl(data2, addr2, ctx->mem_idx, memop); return true; diff --git a/target/riscv/insn_trans/trans_zilsd.c.inc b/target/riscv/insn_trans/trans_zilsd.c.inc index f50c52f22c..8068cc1aec 100644 --- a/target/riscv/insn_trans/trans_zilsd.c.inc +++ b/target/riscv/insn_trans/trans_zilsd.c.inc @@ -30,7 +30,7 @@ static bool gen_load_i64(DisasContext *ctx, arg_ld *a) TCGv addr = get_address(ctx, a->rs1, a->imm); TCGv_i64 tmp = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_SQ | mo_endian(ctx)); + tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_SQ | ctx->mo_endianness); if (a->rd == 0) { return true; @@ -85,7 +85,7 @@ static bool gen_store_i64(DisasContext *ctx, arg_sd *a) } else { tcg_gen_concat_tl_i64(tmp, data_low, data_high); } - tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_SQ | mo_endian(ctx)); + tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_SQ | ctx->mo_endianness); return true; } diff --git a/target/riscv/internals.h b/target/riscv/internals.h index bac6c8032a..dc505a9ab3 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 02c98cc2db..81b56e5a62 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -193,6 +193,9 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs) flags = FIELD_DP32(flags, TB_FLAGS, PM_SIGNEXTEND, pm_signext); ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, MISA_EXT, env->misa_ext); + if (riscv_cpu_data_is_big_endian(env)) { + ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, BIG_ENDIAN, 1); + } return (TCGTBCPUState){ .pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc, diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 1e4f340256..35c6b37c0b 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -120,6 +120,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 */ + MemOp mo_endianness; } DisasContext; static inline bool has_ext(DisasContext *ctx, uint32_t ext) @@ -127,18 +129,6 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext) return ctx->misa_ext & 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; -} - #ifdef TARGET_RISCV32 #define get_xl(ctx) MXL_RV32 #elif defined(CONFIG_USER_ONLY) @@ -155,7 +145,7 @@ static inline MemOp mo_endian(DisasContext *ctx) #define get_address_xl(ctx) ((ctx)->address_xl) #endif -#define mxl_memop(ctx) ((get_xl(ctx) + 1) | mo_endian(ctx)) +#define mxl_memop(ctx) ((get_xl(ctx) + 1) | (ctx)->mo_endianness) /* The word size for this machine mode. */ static inline int __attribute__((unused)) get_xlen(DisasContext *ctx) @@ -1156,7 +1146,7 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a, TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE); MemOp size = mop & MO_SIZE; - mop |= mo_endian(ctx); + mop |= ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b && size >= MO_32) { mop |= MO_ATOM_WITHIN16; } else { @@ -1177,7 +1167,7 @@ static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGv src1 = get_address(ctx, a->rs1, 0); TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); - mop |= mo_endian(ctx); + mop |= ctx->mo_endianness; decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop); @@ -1360,6 +1350,8 @@ 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->mo_endianness = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS, BIG_ENDIAN) + ? MO_BE : MO_LE; } static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu) -- 2.34.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v9 4/7] hw/riscv: Make boot code endianness-aware at runtime 2026-05-11 8:38 [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic ` (2 preceding siblings ...) 2026-05-11 8:38 ` [PATCH v9 3/7] target/riscv: Implement runtime data endianness via MSTATUS bits Djordje Todorovic @ 2026-05-11 8:38 ` Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 5/7] target/riscv: Fix page table walk endianness for big-endian harts Djordje Todorovic ` (4 subsequent siblings) 8 siblings, 0 replies; 14+ messages in thread From: Djordje Todorovic @ 2026-05-11 8:38 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 | 81 +++++++++++++++++++++++++++++++++++------ include/hw/riscv/boot.h | 1 + 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 9086793b7a..37b8f3dfa7 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()) @@ -262,8 +284,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; @@ -406,21 +429,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; @@ -489,10 +523,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..93b9a37f03 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -39,6 +39,7 @@ typedef struct RISCVBootInfo { } 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] 14+ messages in thread
* [PATCH v9 5/7] target/riscv: Fix page table walk endianness for big-endian harts 2026-05-11 8:38 [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic ` (3 preceding siblings ...) 2026-05-11 8:38 ` [PATCH v9 4/7] hw/riscv: Make boot code endianness-aware at runtime Djordje Todorovic @ 2026-05-11 8:38 ` Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 6/7] target/riscv: Expose big-endian CPU property and add documentation Djordje Todorovic ` (3 subsequent siblings) 8 siblings, 0 replies; 14+ messages in thread From: Djordje Todorovic @ 2026-05-11 8:38 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 39c3486ae0..4859b8dd5c 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -1418,9 +1418,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) { @@ -1619,12 +1623,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] 14+ messages in thread
* [PATCH v9 6/7] target/riscv: Expose big-endian CPU property and add documentation 2026-05-11 8:38 [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic ` (4 preceding siblings ...) 2026-05-11 8:38 ` [PATCH v9 5/7] target/riscv: Fix page table walk endianness for big-endian harts Djordje Todorovic @ 2026-05-11 8:38 ` Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 7/7] target/riscv: Add endianness test for RISC-V BE Djordje Todorovic ` (2 subsequent siblings) 8 siblings, 0 replies; 14+ messages in thread From: Djordje Todorovic @ 2026-05-11 8:38 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 Now that the full big-endian data path is in place (runtime MSTATUS bits, boot code, and page-table walks), expose the "big-endian" property to users via DEFINE_PROP_BOOL and document it in docs/system/target-riscv.rst. The property can be enabled from the command line, e.g.: -cpu <cpu>,big-endian=on Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com> --- docs/system/target-riscv.rst | 24 ++++++++++++++++++++++++ target/riscv/cpu.c | 1 + 2 files changed, 25 insertions(+) diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst index 3ad5d1ddaf..7798184ebe 100644 --- a/docs/system/target-riscv.rst +++ b/docs/system/target-riscv.rst @@ -95,3 +95,27 @@ the images they need. * ``-bios <file>`` Tells QEMU to load the specified file as the firmware. + +RISC-V CPU endianness +--------------------- + +The RISC-V ISA specifies that instruction fetches are always little-endian, +while data accesses can be either little-endian or big-endian under control +of the MSTATUS ``MBE``/``SBE``/``UBE`` bits (see section 3.1.6.5, "Memory +Endianness", in the RISC-V Privileged Specification). + +QEMU implements the full data-endianness behaviour described by those bits. +In addition, the RISC-V CPU object exposes a ``big-endian`` boolean property +which models a big-endian-only hardware implementation, where the +``MBE``/``SBE``/``UBE`` bits are hardwired to 1. When the property is set, +the CPU is reset with all three bits initialised to 1, so the guest starts +executing in big-endian data mode from the reset vector. The property is a +static, per-CPU hardware configuration option and is not meant to be toggled +at runtime. + +The property can be enabled from the command line, for example:: + + -cpu <cpu>,big-endian=on + +No upstream CPU model currently defaults to big-endian; the property is +provided so that big-endian-only RISC-V CPU variants can be modelled. diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ae75019186..f1fff92d4b 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -2657,6 +2657,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 */ -- 2.34.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v9 7/7] target/riscv: Add endianness test for RISC-V BE 2026-05-11 8:38 [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic ` (5 preceding siblings ...) 2026-05-11 8:38 ` [PATCH v9 6/7] target/riscv: Expose big-endian CPU property and add documentation Djordje Todorovic @ 2026-05-11 8:38 ` Djordje Todorovic 2026-05-20 14:08 ` [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic 2026-05-20 14:12 ` Michael S. Tsirkin 8 siblings, 0 replies; 14+ messages in thread From: Djordje Todorovic @ 2026-05-11 8:38 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> Reviewed-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> --- tests/functional/riscv64/meson.build | 1 + tests/functional/riscv64/test_endianness.py | 57 +++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 tests/functional/riscv64/test_endianness.py diff --git a/tests/functional/riscv64/meson.build b/tests/functional/riscv64/meson.build index b996c89d7d..5871211e89 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 = [ + 'endianness', 'boston', 'sifive_u', 'tuxrun', diff --git a/tests/functional/riscv64/test_endianness.py b/tests/functional/riscv64/test_endianness.py new file mode 100644 index 0000000000..9e0b3b7db5 --- /dev/null +++ b/tests/functional/riscv64/test_endianness.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] 14+ messages in thread
* Re: [PATCH v9 0/7] Add RISC-V big-endian target support 2026-05-11 8:38 [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic ` (6 preceding siblings ...) 2026-05-11 8:38 ` [PATCH v9 7/7] target/riscv: Add endianness test for RISC-V BE Djordje Todorovic @ 2026-05-20 14:08 ` Djordje Todorovic 2026-05-20 17:19 ` Philippe Mathieu-Daudé 2026-05-20 14:12 ` Michael S. Tsirkin 8 siblings, 1 reply; 14+ messages in thread From: Djordje Todorovic @ 2026-05-20 14:08 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 Hi all, I am wondering, if there is any comment on v9. :) Thanks a lot! Djordje On 5/11/26 10:38, Djordje Todorovic wrote: > Rebase on top of master. > > Djordje Todorovic (7): > target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks > target/riscv: Add big-endian CPU configuration field and reset logic > 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: Expose big-endian CPU property and add documentation > target/riscv: Add endianness test for RISC-V BE > > docs/system/target-riscv.rst | 24 ++++++ > hw/riscv/boot.c | 81 ++++++++++++++++--- > include/hw/riscv/boot.h | 1 + > target/riscv/cpu.c | 11 +-- > target/riscv/cpu.h | 23 ++++++ > target/riscv/cpu_bits.h | 2 + > target/riscv/cpu_cfg_fields.h.inc | 1 + > target/riscv/cpu_helper.c | 28 +++++-- > target/riscv/insn_trans/trans_rva.c.inc | 4 +- > target/riscv/insn_trans/trans_rvd.c.inc | 4 +- > target/riscv/insn_trans/trans_rvf.c.inc | 4 +- > target/riscv/insn_trans/trans_rvi.c.inc | 8 +- > target/riscv/insn_trans/trans_rvzacas.c.inc | 4 +- > target/riscv/insn_trans/trans_rvzalasr.c.inc | 4 +- > target/riscv/insn_trans/trans_rvzce.c.inc | 4 +- > target/riscv/insn_trans/trans_rvzfh.c.inc | 4 +- > target/riscv/insn_trans/trans_rvzicfiss.c.inc | 4 +- > target/riscv/insn_trans/trans_xmips.c.inc | 8 +- > target/riscv/insn_trans/trans_xthead.c.inc | 16 ++-- > target/riscv/insn_trans/trans_zilsd.c.inc | 4 +- > target/riscv/internals.h | 9 +-- > target/riscv/tcg/tcg-cpu.c | 3 + > target/riscv/translate.c | 22 ++--- > tests/functional/riscv64/meson.build | 1 + > tests/functional/riscv64/test_endianness.py | 57 +++++++++++++ > 25 files changed, 251 insertions(+), 80 deletions(-) > create mode 100644 tests/functional/riscv64/test_endianness.py > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v9 0/7] Add RISC-V big-endian target support 2026-05-20 14:08 ` [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic @ 2026-05-20 17:19 ` Philippe Mathieu-Daudé 2026-05-26 14:50 ` Djordje Todorovic 0 siblings, 1 reply; 14+ messages in thread From: Philippe Mathieu-Daudé @ 2026-05-20 17: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 20/5/26 16:08, Djordje Todorovic wrote: > Hi all, > > I am wondering, if there is any comment on v9. :) > > Thanks a lot! > Djordje > > > On 5/11/26 10:38, Djordje Todorovic wrote: >> Rebase on top of master. More than a "rebase" comment I was hoping to read what was the conclusion on previous versions about wired endianness bits. >> >> Djordje Todorovic (7): >> target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks >> target/riscv: Add big-endian CPU configuration field and reset logic >> 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: Expose big-endian CPU property and add documentation >> target/riscv: Add endianness test for RISC-V BE >> >> docs/system/target-riscv.rst | 24 ++++++ >> hw/riscv/boot.c | 81 ++++++++++++++++--- >> include/hw/riscv/boot.h | 1 + >> target/riscv/cpu.c | 11 +-- >> target/riscv/cpu.h | 23 ++++++ >> target/riscv/cpu_bits.h | 2 + >> target/riscv/cpu_cfg_fields.h.inc | 1 + >> target/riscv/cpu_helper.c | 28 +++++-- >> target/riscv/insn_trans/trans_rva.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvd.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvf.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvi.c.inc | 8 +- >> target/riscv/insn_trans/trans_rvzacas.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvzalasr.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvzce.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvzfh.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvzicfiss.c.inc | 4 +- >> target/riscv/insn_trans/trans_xmips.c.inc | 8 +- >> target/riscv/insn_trans/trans_xthead.c.inc | 16 ++-- >> target/riscv/insn_trans/trans_zilsd.c.inc | 4 +- >> target/riscv/internals.h | 9 +-- >> target/riscv/tcg/tcg-cpu.c | 3 + >> target/riscv/translate.c | 22 ++--- >> tests/functional/riscv64/meson.build | 1 + >> tests/functional/riscv64/test_endianness.py | 57 +++++++++++++ >> 25 files changed, 251 insertions(+), 80 deletions(-) >> create mode 100644 tests/functional/riscv64/test_endianness.py >> ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v9 0/7] Add RISC-V big-endian target support 2026-05-20 17:19 ` Philippe Mathieu-Daudé @ 2026-05-26 14:50 ` Djordje Todorovic 0 siblings, 0 replies; 14+ messages in thread From: Djordje Todorovic @ 2026-05-26 14:50 UTC (permalink / raw) To: Philippe Mathieu-Daudé, 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 5/20/26 19:19, Philippe Mathieu-Daudé wrote: > CAUTION: This email originated from outside of the organization. Do > not click links or open attachments unless you recognize the sender > and know the content is safe. > > > On 20/5/26 16:08, Djordje Todorovic wrote: >> Hi all, >> >> I am wondering, if there is any comment on v9. :) >> >> Thanks a lot! >> Djordje >> >> >> On 5/11/26 10:38, Djordje Todorovic wrote: >>> Rebase on top of master. > > More than a "rebase" comment I was hoping to read what was the > conclusion on previous versions about wired endianness bits. > Yes, sorry, I should have made that clearer in the cover letter. This was partially addressed in v7 by making `big-endian` a static CPU configuration option rather than a runtime switch. In v10 I made the intended model explicit: this series models fixed-endian harts, not a mixed-endian implementation where software can toggle MBE/SBE/UBE at runtime. The reset value of MBE/SBE/UBE is selected from the CPU configuration, and the bits remain outside the mstatus/mstatush/sstatus writable masks, so they are effectively hardwired to 0 for the default little-endian CPUs and to 1 when `big-endian=on`. I also documented this in the patches and will mention it explicitly in the v10 cover letter. >>> >>> Djordje Todorovic (7): >>> target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks >>> target/riscv: Add big-endian CPU configuration field and reset >>> logic >>> 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: Expose big-endian CPU property and add documentation >>> target/riscv: Add endianness test for RISC-V BE >>> >>> docs/system/target-riscv.rst | 24 ++++++ >>> hw/riscv/boot.c | 81 >>> ++++++++++++++++--- >>> include/hw/riscv/boot.h | 1 + >>> target/riscv/cpu.c | 11 +-- >>> target/riscv/cpu.h | 23 ++++++ >>> target/riscv/cpu_bits.h | 2 + >>> target/riscv/cpu_cfg_fields.h.inc | 1 + >>> target/riscv/cpu_helper.c | 28 +++++-- >>> target/riscv/insn_trans/trans_rva.c.inc | 4 +- >>> target/riscv/insn_trans/trans_rvd.c.inc | 4 +- >>> target/riscv/insn_trans/trans_rvf.c.inc | 4 +- >>> target/riscv/insn_trans/trans_rvi.c.inc | 8 +- >>> target/riscv/insn_trans/trans_rvzacas.c.inc | 4 +- >>> target/riscv/insn_trans/trans_rvzalasr.c.inc | 4 +- >>> target/riscv/insn_trans/trans_rvzce.c.inc | 4 +- >>> target/riscv/insn_trans/trans_rvzfh.c.inc | 4 +- >>> target/riscv/insn_trans/trans_rvzicfiss.c.inc | 4 +- >>> target/riscv/insn_trans/trans_xmips.c.inc | 8 +- >>> target/riscv/insn_trans/trans_xthead.c.inc | 16 ++-- >>> target/riscv/insn_trans/trans_zilsd.c.inc | 4 +- >>> target/riscv/internals.h | 9 +-- >>> target/riscv/tcg/tcg-cpu.c | 3 + >>> target/riscv/translate.c | 22 ++--- >>> tests/functional/riscv64/meson.build | 1 + >>> tests/functional/riscv64/test_endianness.py | 57 +++++++++++++ >>> 25 files changed, 251 insertions(+), 80 deletions(-) >>> create mode 100644 tests/functional/riscv64/test_endianness.py >>> > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v9 0/7] Add RISC-V big-endian target support 2026-05-11 8:38 [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic ` (7 preceding siblings ...) 2026-05-20 14:08 ` [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic @ 2026-05-20 14:12 ` Michael S. Tsirkin 2026-05-20 17:47 ` Philippe Mathieu-Daudé 8 siblings, 1 reply; 14+ messages in thread From: Michael S. Tsirkin @ 2026-05-20 14:12 UTC (permalink / raw) To: Djordje Todorovic Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org, cfu@mips.com, marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com, philmd@linaro.org, alistair23@gmail.com, thuth@redhat.com On Mon, May 11, 2026 at 08:38:26AM +0000, Djordje Todorovic wrote: > Rebase on top of master. is Linux going to support this, ever? given this history: https://lore.kernel.org/lkml/CAHk-%3DwgYcOiFvsJzFb%2BHfB4n6Wj6zM5H5EghUMfpXSCzyQVSfA@mail.gmail.com/t/#mce138059dc56014643bbda330810183031ef5c06 pls include a cover letter explaining why we should bother with this. > Djordje Todorovic (7): > target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks > target/riscv: Add big-endian CPU configuration field and reset logic > 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: Expose big-endian CPU property and add documentation > target/riscv: Add endianness test for RISC-V BE > > docs/system/target-riscv.rst | 24 ++++++ > hw/riscv/boot.c | 81 ++++++++++++++++--- > include/hw/riscv/boot.h | 1 + > target/riscv/cpu.c | 11 +-- > target/riscv/cpu.h | 23 ++++++ > target/riscv/cpu_bits.h | 2 + > target/riscv/cpu_cfg_fields.h.inc | 1 + > target/riscv/cpu_helper.c | 28 +++++-- > target/riscv/insn_trans/trans_rva.c.inc | 4 +- > target/riscv/insn_trans/trans_rvd.c.inc | 4 +- > target/riscv/insn_trans/trans_rvf.c.inc | 4 +- > target/riscv/insn_trans/trans_rvi.c.inc | 8 +- > target/riscv/insn_trans/trans_rvzacas.c.inc | 4 +- > target/riscv/insn_trans/trans_rvzalasr.c.inc | 4 +- > target/riscv/insn_trans/trans_rvzce.c.inc | 4 +- > target/riscv/insn_trans/trans_rvzfh.c.inc | 4 +- > target/riscv/insn_trans/trans_rvzicfiss.c.inc | 4 +- > target/riscv/insn_trans/trans_xmips.c.inc | 8 +- > target/riscv/insn_trans/trans_xthead.c.inc | 16 ++-- > target/riscv/insn_trans/trans_zilsd.c.inc | 4 +- > target/riscv/internals.h | 9 +-- > target/riscv/tcg/tcg-cpu.c | 3 + > target/riscv/translate.c | 22 ++--- > tests/functional/riscv64/meson.build | 1 + > tests/functional/riscv64/test_endianness.py | 57 +++++++++++++ > 25 files changed, 251 insertions(+), 80 deletions(-) > create mode 100644 tests/functional/riscv64/test_endianness.py > > -- > 2.34.1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v9 0/7] Add RISC-V big-endian target support 2026-05-20 14:12 ` Michael S. Tsirkin @ 2026-05-20 17:47 ` Philippe Mathieu-Daudé 0 siblings, 0 replies; 14+ messages in thread From: Philippe Mathieu-Daudé @ 2026-05-20 17:47 UTC (permalink / raw) To: Michael S. Tsirkin, Djordje Todorovic Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org, cfu@mips.com, marcel.apfelbaum@gmail.com, dbarboza@ventanamicro.com, alistair23@gmail.com, thuth@redhat.com On 20/5/26 16:12, Michael S. Tsirkin wrote: > On Mon, May 11, 2026 at 08:38:26AM +0000, Djordje Todorovic wrote: >> Rebase on top of master. > > is Linux going to support this, ever? given this history: > > https://lore.kernel.org/lkml/CAHk-%3DwgYcOiFvsJzFb%2BHfB4n6Wj6zM5H5EghUMfpXSCzyQVSfA@mail.gmail.com/t/#mce138059dc56014643bbda330810183031ef5c06 > > pls include a cover letter explaining why we should bother with this. We can run any kind of guests, not limiting ourselves to Linux kernel. > >> Djordje Todorovic (7): >> target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks >> target/riscv: Add big-endian CPU configuration field and reset logic >> 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: Expose big-endian CPU property and add documentation >> target/riscv: Add endianness test for RISC-V BE >> >> docs/system/target-riscv.rst | 24 ++++++ >> hw/riscv/boot.c | 81 ++++++++++++++++--- >> include/hw/riscv/boot.h | 1 + >> target/riscv/cpu.c | 11 +-- >> target/riscv/cpu.h | 23 ++++++ >> target/riscv/cpu_bits.h | 2 + >> target/riscv/cpu_cfg_fields.h.inc | 1 + >> target/riscv/cpu_helper.c | 28 +++++-- >> target/riscv/insn_trans/trans_rva.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvd.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvf.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvi.c.inc | 8 +- >> target/riscv/insn_trans/trans_rvzacas.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvzalasr.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvzce.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvzfh.c.inc | 4 +- >> target/riscv/insn_trans/trans_rvzicfiss.c.inc | 4 +- >> target/riscv/insn_trans/trans_xmips.c.inc | 8 +- >> target/riscv/insn_trans/trans_xthead.c.inc | 16 ++-- >> target/riscv/insn_trans/trans_zilsd.c.inc | 4 +- >> target/riscv/internals.h | 9 +-- >> target/riscv/tcg/tcg-cpu.c | 3 + >> target/riscv/translate.c | 22 ++--- >> tests/functional/riscv64/meson.build | 1 + >> tests/functional/riscv64/test_endianness.py | 57 +++++++++++++ >> 25 files changed, 251 insertions(+), 80 deletions(-) >> create mode 100644 tests/functional/riscv64/test_endianness.py >> >> -- >> 2.34.1 > ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-05-26 14:51 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-11 8:38 [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 2/7] target/riscv: Add big-endian CPU configuration field and reset logic Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 1/7] target/riscv: Define MSTATUS_SBE and MSTATUS_MBE bit masks Djordje Todorovic 2026-05-12 2:31 ` Chao Liu 2026-05-11 8:38 ` [PATCH v9 3/7] target/riscv: Implement runtime data endianness via MSTATUS bits Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 4/7] hw/riscv: Make boot code endianness-aware at runtime Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 5/7] target/riscv: Fix page table walk endianness for big-endian harts Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 6/7] target/riscv: Expose big-endian CPU property and add documentation Djordje Todorovic 2026-05-11 8:38 ` [PATCH v9 7/7] target/riscv: Add endianness test for RISC-V BE Djordje Todorovic 2026-05-20 14:08 ` [PATCH v9 0/7] Add RISC-V big-endian target support Djordje Todorovic 2026-05-20 17:19 ` Philippe Mathieu-Daudé 2026-05-26 14:50 ` Djordje Todorovic 2026-05-20 14:12 ` Michael S. Tsirkin 2026-05-20 17:47 ` Philippe Mathieu-Daudé
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.