From 38f4a833a4dcf0b02ebc2653f8c7163321f4b438 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Wed, 21 Feb 2018 02:12:16 -0500 Subject: [PATCH] arm: cpu: handle BE32 user-mode as BE endian with address manipulations on subword accesses (to give the illusion of BE). But user-mode cannot tell the difference and is already implemented as straight BE. So handle the difference in the endianess query, where USER mode is BE and system is not. Backports commit b2e62d9a7b9a2eb10e451a57813bad168376e122 from qemu --- qemu/target-arm/cpu.h | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/qemu/target-arm/cpu.h b/qemu/target-arm/cpu.h index 434af518..d00846d3 100644 --- a/qemu/target-arm/cpu.h +++ b/qemu/target-arm/cpu.h @@ -2174,7 +2174,22 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env) /* In 32bit endianness is determined by looking at CPSR's E bit */ if (!is_a64(env)) { - return (env->uncached_cpsr & CPSR_E) ? 1 : 0; + return +#ifdef CONFIG_USER_ONLY + /* In system mode, BE32 is modelled in line with the + * architecture (as word-invariant big-endianness), where loads + * and stores are done little endian but from addresses which + * are adjusted by XORing with the appropriate constant. So the + * endianness to use for the raw data access is not affected by + * SCTLR.B. + * In user mode, however, we model BE32 as byte-invariant + * big-endianness (because user-only code cannot tell the + * difference), and so we need to use a data access endianness + * that depends on SCTLR.B. + */ + arm_sctlr_b(env) || +#endif + ((env->uncached_cpsr & CPSR_E) ? 1 : 0); } cur_el = arm_current_el(env);