All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v1 00/17]  ARM big-endian and setend support
@ 2016-01-18  7:12 Peter Crosthwaite
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 01/17] linux-user: arm: fix coding style for some linux-user signal functions Peter Crosthwaite
                   ` (18 more replies)
  0 siblings, 19 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

Hi All,

This patch series adds system-mode big-endian support for ARM. It also
implements the setend instruction, and loading of BE binaries even in
LE emulation mode.

Based on Paolo's original work. I have moved all the BE32 related work
to the back of the series. Multiple parties are interested in the BE8
work just on its own, so that could potentially be merged w/o BE32.
PMM requested BE32 be at least thought out architecturally, so this
series sees BE32 functionality through.

I have tested all of LE. BE8 and BE32 in both linux-user mode (for
regressions) and system mode (BE8 and BE32 are new here).
My test application is here, the README gives some example command
lines you can run:

https://github.com/pcrost/arm-be-test

Regards,
Peter


Paolo Bonzini (8):
  linux-user: arm: fix coding style for some linux-user signal functions
  linux-user: arm: handle CPSR.E correctly in strex emulation
  target-arm: pass DisasContext to gen_aa32_ld*/st*
  target-arm: introduce disas flag for endianness
  target-arm: implement setend
  linux-user: arm: pass env to get_user_code_*
  target-arm: implement SCTLR.B, drop bswap_code
  target-arm: implement BE32 mode in system emulation

Peter Crosthwaite (9):
  linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode
  target-arm: implement SCTLR.EE
  target-arm: a64: Add endianness support
  target-arm: cpu: Move cpu_is_big_endian to header
  target-arm: introduce tbflag for endianness
  arm: linux-user: don't set CPSR.E in BE32 mode
  loader: add API to load elf header
  loader: Add data swap option to load-elf
  arm: boot: Support big-endian elfs

 hw/alpha/dp264.c               |   4 +-
 hw/arm/armv7m.c                |   2 +-
 hw/arm/boot.c                  |  96 ++++++++--
 hw/core/loader.c               |  57 +++++-
 hw/cris/boot.c                 |   2 +-
 hw/i386/multiboot.c            |   3 +-
 hw/lm32/lm32_boards.c          |   4 +-
 hw/lm32/milkymist.c            |   2 +-
 hw/m68k/an5206.c               |   2 +-
 hw/m68k/dummy_m68k.c           |   2 +-
 hw/m68k/mcf5208.c              |   2 +-
 hw/microblaze/boot.c           |   4 +-
 hw/mips/mips_fulong2e.c        |   2 +-
 hw/mips/mips_malta.c           |   2 +-
 hw/mips/mips_mipssim.c         |   2 +-
 hw/mips/mips_r4k.c             |   2 +-
 hw/moxie/moxiesim.c            |   3 +-
 hw/openrisc/openrisc_sim.c     |   3 +-
 hw/pci-host/prep.c             |   2 +-
 hw/ppc/e500.c                  |   2 +-
 hw/ppc/mac_newworld.c          |   5 +-
 hw/ppc/mac_oldworld.c          |   5 +-
 hw/ppc/ppc440_bamboo.c         |   3 +-
 hw/ppc/spapr.c                 |   6 +-
 hw/ppc/virtex_ml507.c          |   3 +-
 hw/s390x/ipl.c                 |   4 +-
 hw/sparc/leon3.c               |   2 +-
 hw/sparc/sun4m.c               |   4 +-
 hw/sparc64/sun4u.c             |   4 +-
 hw/tricore/tricore_testboard.c |   2 +-
 hw/xtensa/sim.c                |   4 +-
 hw/xtensa/xtfpga.c             |   2 +-
 include/hw/arm/arm.h           |   9 +
 include/hw/elf_ops.h           |  22 ++-
 include/hw/loader.h            |   3 +-
 linux-user/main.c              |  77 ++++++--
 linux-user/signal.c            | 110 +++++------
 target-arm/arm_ldst.h          |   8 +-
 target-arm/cpu.c               |  21 +--
 target-arm/cpu.h               | 103 ++++++++++-
 target-arm/helper.c            |  50 +++--
 target-arm/helper.h            |   1 +
 target-arm/op_helper.c         |   5 +
 target-arm/translate-a64.c     |  56 +++---
 target-arm/translate.c         | 407 ++++++++++++++++++++++++-----------------
 target-arm/translate.h         |   3 +-
 46 files changed, 752 insertions(+), 365 deletions(-)

-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 01/17] linux-user: arm: fix coding style for some linux-user signal functions
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 02/17] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode Peter Crosthwaite
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 linux-user/signal.c | 110 ++++++++++++++++++++++++++--------------------------
 1 file changed, 56 insertions(+), 54 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 919aa83..2cc6d73 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1541,82 +1541,84 @@ static void
 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
                  CPUARMState *env, abi_ulong mask)
 {
-	__put_user(env->regs[0], &sc->arm_r0);
-	__put_user(env->regs[1], &sc->arm_r1);
-	__put_user(env->regs[2], &sc->arm_r2);
-	__put_user(env->regs[3], &sc->arm_r3);
-	__put_user(env->regs[4], &sc->arm_r4);
-	__put_user(env->regs[5], &sc->arm_r5);
-	__put_user(env->regs[6], &sc->arm_r6);
-	__put_user(env->regs[7], &sc->arm_r7);
-	__put_user(env->regs[8], &sc->arm_r8);
-	__put_user(env->regs[9], &sc->arm_r9);
-	__put_user(env->regs[10], &sc->arm_r10);
-	__put_user(env->regs[11], &sc->arm_fp);
-	__put_user(env->regs[12], &sc->arm_ip);
-	__put_user(env->regs[13], &sc->arm_sp);
-	__put_user(env->regs[14], &sc->arm_lr);
-	__put_user(env->regs[15], &sc->arm_pc);
+    __put_user(env->regs[0], &sc->arm_r0);
+    __put_user(env->regs[1], &sc->arm_r1);
+    __put_user(env->regs[2], &sc->arm_r2);
+    __put_user(env->regs[3], &sc->arm_r3);
+    __put_user(env->regs[4], &sc->arm_r4);
+    __put_user(env->regs[5], &sc->arm_r5);
+    __put_user(env->regs[6], &sc->arm_r6);
+    __put_user(env->regs[7], &sc->arm_r7);
+    __put_user(env->regs[8], &sc->arm_r8);
+    __put_user(env->regs[9], &sc->arm_r9);
+    __put_user(env->regs[10], &sc->arm_r10);
+    __put_user(env->regs[11], &sc->arm_fp);
+    __put_user(env->regs[12], &sc->arm_ip);
+    __put_user(env->regs[13], &sc->arm_sp);
+    __put_user(env->regs[14], &sc->arm_lr);
+    __put_user(env->regs[15], &sc->arm_pc);
 #ifdef TARGET_CONFIG_CPU_32
-	__put_user(cpsr_read(env), &sc->arm_cpsr);
+    __put_user(cpsr_read(env), &sc->arm_cpsr);
 #endif
 
-	__put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
-	__put_user(/* current->thread.error_code */ 0, &sc->error_code);
-	__put_user(/* current->thread.address */ 0, &sc->fault_address);
-	__put_user(mask, &sc->oldmask);
+    __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
+    __put_user(/* current->thread.error_code */ 0, &sc->error_code);
+    __put_user(/* current->thread.address */ 0, &sc->fault_address);
+    __put_user(mask, &sc->oldmask);
 }
 
 static inline abi_ulong
 get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
 {
-	unsigned long sp = regs->regs[13];
+    unsigned long sp = regs->regs[13];
 
-	/*
-	 * This is the X/Open sanctioned signal stack switching.
-	 */
-	if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
-            sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
-	/*
-	 * ATPCS B01 mandates 8-byte alignment
-	 */
-	return (sp - framesize) & ~7;
+    /*
+     * This is the X/Open sanctioned signal stack switching.
+     */
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
+        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+    }
+    /*
+     * ATPCS B01 mandates 8-byte alignment
+     */
+    return (sp - framesize) & ~7;
 }
 
 static void
 setup_return(CPUARMState *env, struct target_sigaction *ka,
 	     abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
 {
-	abi_ulong handler = ka->_sa_handler;
-	abi_ulong retcode;
-	int thumb = handler & 1;
-	uint32_t cpsr = cpsr_read(env);
+    abi_ulong handler = ka->_sa_handler;
+    abi_ulong retcode;
+    int thumb = handler & 1;
+    uint32_t cpsr = cpsr_read(env);
 
-	cpsr &= ~CPSR_IT;
-	if (thumb) {
-		cpsr |= CPSR_T;
-	} else {
-		cpsr &= ~CPSR_T;
-	}
+    cpsr &= ~CPSR_IT;
+    if (thumb) {
+        cpsr |= CPSR_T;
+    } else {
+        cpsr &= ~CPSR_T;
+    }
 
-	if (ka->sa_flags & TARGET_SA_RESTORER) {
-		retcode = ka->sa_restorer;
-	} else {
-		unsigned int idx = thumb;
+    if (ka->sa_flags & TARGET_SA_RESTORER) {
+        retcode = ka->sa_restorer;
+    } else {
+        unsigned int idx = thumb;
 
-		if (ka->sa_flags & TARGET_SA_SIGINFO)
-			idx += 2;
+        if (ka->sa_flags & TARGET_SA_SIGINFO) {
+            idx += 2;
+        }
 
         __put_user(retcodes[idx], rc);
 
-		retcode = rc_addr + thumb;
-	}
+        retcode = rc_addr + thumb;
+    }
 
-	env->regs[0] = usig;
-	env->regs[13] = frame_addr;
-	env->regs[14] = retcode;
-	env->regs[15] = handler & (thumb ? ~1 : ~3);
-	cpsr_write(env, cpsr, 0xffffffff);
+    env->regs[0] = usig;
+    env->regs[13] = frame_addr;
+    env->regs[14] = retcode;
+    env->regs[15] = handler & (thumb ? ~1 : ~3);
+    cpsr_write(env, cpsr, 0xffffffff);
 }
 
 static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 02/17] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 01/17] linux-user: arm: fix coding style for some linux-user signal functions Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 16:22   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 03/17] linux-user: arm: handle CPSR.E correctly in strex emulation Peter Crosthwaite
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>

If doing big-endian linux-user mode, set both the CPSR.E and SCTLR.E0E
bits. This sets big-endian mode for data accesses in AA32 and AA64
resp.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---

 linux-user/main.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/linux-user/main.c b/linux-user/main.c
index ee12035..4f8ea9c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4454,6 +4454,10 @@ int main(int argc, char **argv, char **envp)
         for(i = 0; i < 16; i++) {
             env->regs[i] = regs->uregs[i];
         }
+#ifdef TARGET_WORDS_BIGENDIAN
+        env->uncached_cpsr |= CPSR_E;
+        env->cp15.sctlr_el[1] |= SCTLR_E0E;
+#endif
         /* Enable BE8.  */
         if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
             && (info->elf_flags & EF_ARM_BE8)) {
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 03/17] linux-user: arm: handle CPSR.E correctly in strex emulation
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 01/17] linux-user: arm: fix coding style for some linux-user signal functions Peter Crosthwaite
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 02/17] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 16:24   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 04/17] target-arm: implement SCTLR.EE Peter Crosthwaite
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Paolo Bonzini <pbonzini@redhat.com>

Now that CPSR.E is set correctly, prepare for when setend will be able
to change it; bswap data in and out of strex manually by comparing
SCTLR.B, CPSR.E and TARGET_WORDS_BIGENDIAN (we do not have the luxury
of using TCGMemOps).

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[ PC changes:
  * Remove BE32 support
]
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 linux-user/main.c | 50 +++++++++++++++++++++++++++++++++++++++++++-------
 target-arm/cpu.h  | 21 +++++++++++++++++++++
 2 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 4f8ea9c..8348ddc 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -455,6 +455,38 @@ void cpu_loop(CPUX86State *env)
         __r;                                            \
     })
 
+#define get_user_data_u32(x, gaddr, env)                \
+    ({ abi_long __r = get_user_u32((x), (gaddr));       \
+        if (!__r && arm_cpu_bswap_data(env)) {          \
+            (x) = bswap32(x);                           \
+        }                                               \
+        __r;                                            \
+    })
+
+#define get_user_data_u16(x, gaddr, env)                \
+    ({ abi_long __r = get_user_u16((x), (gaddr));       \
+        if (!__r && arm_cpu_bswap_data(env)) {          \
+            (x) = bswap16(x);                           \
+        }                                               \
+        __r;                                            \
+    })
+
+#define put_user_data_u32(x, gaddr, env)                \
+    ({ typeof(x) __x = (x);                             \
+        if (arm_cpu_bswap_data(env)) {                  \
+            __x = bswap32(__x);                         \
+        }                                               \
+        put_user_u32(__x, (gaddr));                     \
+    })
+
+#define put_user_data_u16(x, gaddr, env)                \
+    ({ typeof(x) __x = (x);                             \
+        if (arm_cpu_bswap_data(env)) {                  \
+            __x = bswap16(__x);                         \
+        }                                               \
+        put_user_u16(__x, (gaddr));                     \
+    })
+
 #ifdef TARGET_ABI32
 /* Commpage handling -- there is no commpage for AArch64 */
 
@@ -614,11 +646,11 @@ static int do_strex(CPUARMState *env)
         segv = get_user_u8(val, addr);
         break;
     case 1:
-        segv = get_user_u16(val, addr);
+        segv = get_user_data_u16(val, addr, env);
         break;
     case 2:
     case 3:
-        segv = get_user_u32(val, addr);
+        segv = get_user_data_u32(val, addr, env);
         break;
     default:
         abort();
@@ -629,12 +661,16 @@ static int do_strex(CPUARMState *env)
     }
     if (size == 3) {
         uint32_t valhi;
-        segv = get_user_u32(valhi, addr + 4);
+        segv = get_user_data_u32(valhi, addr + 4, env);
         if (segv) {
             env->exception.vaddress = addr + 4;
             goto done;
         }
-        val = deposit64(val, 32, 32, valhi);
+        if (arm_cpu_bswap_data(env)) {
+            val = deposit64((uint64_t)valhi, 32, 32, val);
+        } else {
+            val = deposit64(val, 32, 32, valhi);
+        }
     }
     if (val != env->exclusive_val) {
         goto fail;
@@ -646,11 +682,11 @@ static int do_strex(CPUARMState *env)
         segv = put_user_u8(val, addr);
         break;
     case 1:
-        segv = put_user_u16(val, addr);
+        segv = put_user_data_u16(val, addr, env);
         break;
     case 2:
     case 3:
-        segv = put_user_u32(val, addr);
+        segv = put_user_data_u32(val, addr, env);
         break;
     }
     if (segv) {
@@ -659,7 +695,7 @@ static int do_strex(CPUARMState *env)
     }
     if (size == 3) {
         val = env->regs[(env->exclusive_info >> 12) & 0xf];
-        segv = put_user_u32(val, addr + 4);
+        segv = put_user_data_u32(val, addr + 4, env);
         if (segv) {
             env->exception.vaddress = addr + 4;
             goto done;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 815fef8..f83070a 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1934,6 +1934,27 @@ static inline int fp_exception_el(CPUARMState *env)
     return 0;
 }
 
+#ifdef CONFIG_USER_ONLY
+/* get_user and put_user respectively return and expect data according
+ * to TARGET_WORDS_BIGENDIAN, but ldrex/strex emulation needs to take
+ * into account CPSR.E.
+ *
+ *            TARGET_WORDS_BIGENDIAN  CPSR.E    need swap?
+ *   LE/LE                 no           0          no
+ *   LE/BE                 no           1          yes
+ *   BE8/LE                yes          0          yes
+ *   BE8/BE                yes          1          no
+ */
+static inline bool arm_cpu_bswap_data(CPUARMState *env)
+{
+    return
+#ifdef TARGET_WORDS_BIGENDIAN
+       !
+#endif
+       !(env->uncached_cpsr & CPSR_E);
+}
+#endif
+
 static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 04/17] target-arm: implement SCTLR.EE
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (2 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 03/17] linux-user: arm: handle CPSR.E correctly in strex emulation Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 15:58   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 05/17] target-arm: pass DisasContext to gen_aa32_ld*/st* Peter Crosthwaite
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>

Implement SCTLR.EE bit which controls data endianess for exceptions
and page table translations. SCTLR.EE is mirrored to the CPSR.E bit
on exception entry.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---

 target-arm/helper.c | 42 ++++++++++++++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 10 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 59d5a41..afac1b2 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5889,7 +5889,10 @@ void arm_cpu_do_interrupt(CPUState *cs)
     /* Clear IT bits.  */
     env->condexec_bits = 0;
     /* Switch to the new mode, and to the correct instruction set.  */
-    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
+    env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_M)) | new_mode;
+    /* Set new mode endianess */
+    env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_E)) |
+        (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE ? CPSR_E : 0);
     env->daif |= mask;
     /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
      * and we should just guard the thumb mode on V4 */
@@ -5958,6 +5961,12 @@ static inline bool regime_translation_disabled(CPUARMState *env,
     return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
 }
 
+static inline bool regime_translation_big_endian(CPUARMState *env,
+                                                 ARMMMUIdx mmu_idx)
+{
+    return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
+}
+
 /* Return the TCR controlling this translation regime */
 static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
@@ -6263,7 +6272,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
  */
 static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
                             ARMMMUIdx mmu_idx, uint32_t *fsr,
-                            ARMMMUFaultInfo *fi)
+                            ARMMMUFaultInfo *fi, bool be)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
@@ -6274,12 +6283,16 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
     if (fi->s1ptw) {
         return 0;
     }
-    return address_space_ldl(cs->as, addr, attrs, NULL);
+    if (be) {
+        return address_space_ldl_be(cs->as, addr, attrs, NULL);
+    } else {
+        return address_space_ldl_le(cs->as, addr, attrs, NULL);
+    }
 }
 
 static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
                             ARMMMUIdx mmu_idx, uint32_t *fsr,
-                            ARMMMUFaultInfo *fi)
+                            ARMMMUFaultInfo *fi, bool be)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
@@ -6290,7 +6303,11 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
     if (fi->s1ptw) {
         return 0;
     }
-    return address_space_ldq(cs->as, addr, attrs, NULL);
+    if (be) {
+        return address_space_ldq_be(cs->as, addr, attrs, NULL);
+    } else {
+        return address_space_ldq_le(cs->as, addr, attrs, NULL);
+    }
 }
 
 static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
@@ -6318,7 +6335,8 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
         goto do_fault;
     }
     desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
-                       mmu_idx, fsr, fi);
+                       mmu_idx, fsr, fi,
+                       regime_translation_big_endian(env, mmu_idx));
     type = (desc & 3);
     domain = (desc >> 5) & 0x0f;
     if (regime_el(env, mmu_idx) == 1) {
@@ -6355,7 +6373,8 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
             table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
         }
         desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
-                           mmu_idx, fsr, fi);
+                           mmu_idx, fsr, fi,
+                           regime_translation_big_endian(env, mmu_idx));
         switch (desc & 3) {
         case 0: /* Page translation fault.  */
             code = 7;
@@ -6437,7 +6456,8 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
         goto do_fault;
     }
     desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
-                       mmu_idx, fsr, fi);
+                       mmu_idx, fsr, fi,
+                       regime_translation_big_endian(env, mmu_idx));
     type = (desc & 3);
     if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
         /* Section translation fault, or attempt to use the encoding
@@ -6489,7 +6509,8 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
         /* Lookup l2 entry.  */
         table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
         desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
-                           mmu_idx, fsr, fi);
+                           mmu_idx, fsr, fi,
+                           regime_translation_big_endian(env, mmu_idx));
         ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
         switch (desc & 3) {
         case 0: /* Page translation fault.  */
@@ -6862,7 +6883,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
         descaddr |= (address >> (stride * (4 - level))) & descmask;
         descaddr &= ~7ULL;
         nstable = extract32(tableattrs, 4, 1);
-        descriptor = arm_ldq_ptw(cs, descaddr, !nstable, mmu_idx, fsr, fi);
+        descriptor = arm_ldq_ptw(cs, descaddr, !nstable, mmu_idx, fsr, fi,
+                                 regime_translation_big_endian(env, mmu_idx));
         if (fi->s1ptw) {
             goto do_fault;
         }
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 05/17] target-arm: pass DisasContext to gen_aa32_ld*/st*
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (3 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 04/17] target-arm: implement SCTLR.EE Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 16:08   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 06/17] target-arm: introduce disas flag for endianness Peter Crosthwaite
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Paolo Bonzini <pbonzini@redhat.com>

We'll need the DisasContext in the next patch to retrieve the
desired endianness, so pass it as a whole to gen_aa32_ld*/st*.

Unfortunately we cannot let those functions call get_mem_index,
because of user-mode load/store instructions.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[ PC changes:
 * Fix long lines
]
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 target-arm/translate.c | 270 ++++++++++++++++++++++++++-----------------------
 1 file changed, 142 insertions(+), 128 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index d485e7d..55ecca5 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -924,23 +924,27 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
 #if TARGET_LONG_BITS == 32
 
 #define DO_GEN_LD(SUFF, OPC)                                             \
-static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,      \
+                                     TCGv_i32 addr, int index)           \
 {                                                                        \
     tcg_gen_qemu_ld_i32(val, addr, index, (OPC));                        \
 }
 
 #define DO_GEN_ST(SUFF, OPC)                                             \
-static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,      \
+                                     TCGv_i32 addr, int index)           \
 {                                                                        \
     tcg_gen_qemu_st_i32(val, addr, index, (OPC));                        \
 }
 
-static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
+                                 TCGv_i32 addr, int index)
 {
     tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
 }
 
-static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
+                                 TCGv_i32 addr, int index)
 {
     tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
 }
@@ -948,7 +952,8 @@ static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
 #else
 
 #define DO_GEN_LD(SUFF, OPC)                                             \
-static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,      \
+                                     TCGv_i32 addr, int index)           \
 {                                                                        \
     TCGv addr64 = tcg_temp_new();                                        \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
@@ -957,7 +962,8 @@ static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 }
 
 #define DO_GEN_ST(SUFF, OPC)                                             \
-static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,      \
+                                     TCGv_i32 addr, int index)           \
 {                                                                        \
     TCGv addr64 = tcg_temp_new();                                        \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
@@ -965,7 +971,8 @@ static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
     tcg_temp_free(addr64);                                               \
 }
 
-static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
+                                 TCGv_i32 addr, int index)
 {
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
@@ -973,7 +980,8 @@ static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
     tcg_temp_free(addr64);
 }
 
-static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
+                                 TCGv_i32 addr, int index)
 {
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
@@ -1288,18 +1296,18 @@ VFP_GEN_FIX(ulto, )
 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
 {
     if (dp) {
-        gen_aa32_ld64(cpu_F0d, addr, get_mem_index(s));
+        gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
     } else {
-        gen_aa32_ld32u(cpu_F0s, addr, get_mem_index(s));
+        gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
     }
 }
 
 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
 {
     if (dp) {
-        gen_aa32_st64(cpu_F0d, addr, get_mem_index(s));
+        gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
     } else {
-        gen_aa32_st32(cpu_F0s, addr, get_mem_index(s));
+        gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
     }
 }
 
@@ -1635,24 +1643,24 @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
         if (insn & ARM_CP_RW_BIT) {
             if ((insn >> 28) == 0xf) {			/* WLDRW wCx */
                 tmp = tcg_temp_new_i32();
-                gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                 iwmmxt_store_creg(wrd, tmp);
             } else {
                 i = 1;
                 if (insn & (1 << 8)) {
                     if (insn & (1 << 22)) {		/* WLDRD */
-                        gen_aa32_ld64(cpu_M0, addr, get_mem_index(s));
+                        gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
                         i = 0;
                     } else {				/* WLDRW wRd */
                         tmp = tcg_temp_new_i32();
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     }
                 } else {
                     tmp = tcg_temp_new_i32();
                     if (insn & (1 << 22)) {		/* WLDRH */
-                        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                     } else {				/* WLDRB */
-                        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                     }
                 }
                 if (i) {
@@ -1664,24 +1672,24 @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
         } else {
             if ((insn >> 28) == 0xf) {			/* WSTRW wCx */
                 tmp = iwmmxt_load_creg(wrd);
-                gen_aa32_st32(tmp, addr, get_mem_index(s));
+                gen_aa32_st32(s, tmp, addr, get_mem_index(s));
             } else {
                 gen_op_iwmmxt_movq_M0_wRn(wrd);
                 tmp = tcg_temp_new_i32();
                 if (insn & (1 << 8)) {
                     if (insn & (1 << 22)) {		/* WSTRD */
-                        gen_aa32_st64(cpu_M0, addr, get_mem_index(s));
+                        gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
                     } else {				/* WSTRW wRd */
                         tcg_gen_extrl_i64_i32(tmp, cpu_M0);
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                     }
                 } else {
                     if (insn & (1 << 22)) {		/* WSTRH */
                         tcg_gen_extrl_i64_i32(tmp, cpu_M0);
-                        gen_aa32_st16(tmp, addr, get_mem_index(s));
+                        gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                     } else {				/* WSTRB */
                         tcg_gen_extrl_i64_i32(tmp, cpu_M0);
-                        gen_aa32_st8(tmp, addr, get_mem_index(s));
+                        gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                     }
                 }
             }
@@ -2746,15 +2754,15 @@ static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
     TCGv_i32 tmp = tcg_temp_new_i32();
     switch (size) {
     case 0:
-        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
         gen_neon_dup_u8(tmp, 0);
         break;
     case 1:
-        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
         gen_neon_dup_low16(tmp);
         break;
     case 2:
-        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
         break;
     default: /* Avoid compiler warnings.  */
         abort();
@@ -4452,11 +4460,11 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
             if (size == 3) {
                 tmp64 = tcg_temp_new_i64();
                 if (load) {
-                    gen_aa32_ld64(tmp64, addr, get_mem_index(s));
+                    gen_aa32_ld64(s, tmp64, addr, get_mem_index(s));
                     neon_store_reg64(tmp64, rd);
                 } else {
                     neon_load_reg64(tmp64, rd);
-                    gen_aa32_st64(tmp64, addr, get_mem_index(s));
+                    gen_aa32_st64(s, tmp64, addr, get_mem_index(s));
                 }
                 tcg_temp_free_i64(tmp64);
                 tcg_gen_addi_i32(addr, addr, stride);
@@ -4465,21 +4473,21 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
                     if (size == 2) {
                         if (load) {
                             tmp = tcg_temp_new_i32();
-                            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                             neon_store_reg(rd, pass, tmp);
                         } else {
                             tmp = neon_load_reg(rd, pass);
-                            gen_aa32_st32(tmp, addr, get_mem_index(s));
+                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                             tcg_temp_free_i32(tmp);
                         }
                         tcg_gen_addi_i32(addr, addr, stride);
                     } else if (size == 1) {
                         if (load) {
                             tmp = tcg_temp_new_i32();
-                            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                             tcg_gen_addi_i32(addr, addr, stride);
                             tmp2 = tcg_temp_new_i32();
-                            gen_aa32_ld16u(tmp2, addr, get_mem_index(s));
+                            gen_aa32_ld16u(s, tmp2, addr, get_mem_index(s));
                             tcg_gen_addi_i32(addr, addr, stride);
                             tcg_gen_shli_i32(tmp2, tmp2, 16);
                             tcg_gen_or_i32(tmp, tmp, tmp2);
@@ -4489,10 +4497,10 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
                             tmp = neon_load_reg(rd, pass);
                             tmp2 = tcg_temp_new_i32();
                             tcg_gen_shri_i32(tmp2, tmp, 16);
-                            gen_aa32_st16(tmp, addr, get_mem_index(s));
+                            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                             tcg_temp_free_i32(tmp);
                             tcg_gen_addi_i32(addr, addr, stride);
-                            gen_aa32_st16(tmp2, addr, get_mem_index(s));
+                            gen_aa32_st16(s, tmp2, addr, get_mem_index(s));
                             tcg_temp_free_i32(tmp2);
                             tcg_gen_addi_i32(addr, addr, stride);
                         }
@@ -4501,7 +4509,7 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
                             TCGV_UNUSED_I32(tmp2);
                             for (n = 0; n < 4; n++) {
                                 tmp = tcg_temp_new_i32();
-                                gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                                gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                                 tcg_gen_addi_i32(addr, addr, stride);
                                 if (n == 0) {
                                     tmp2 = tmp;
@@ -4521,7 +4529,7 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
                                 } else {
                                     tcg_gen_shri_i32(tmp, tmp2, n * 8);
                                 }
-                                gen_aa32_st8(tmp, addr, get_mem_index(s));
+                                gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                                 tcg_temp_free_i32(tmp);
                                 tcg_gen_addi_i32(addr, addr, stride);
                             }
@@ -4645,13 +4653,13 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
                     tmp = tcg_temp_new_i32();
                     switch (size) {
                     case 0:
-                        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                         break;
                     case 1:
-                        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                         break;
                     case 2:
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                         break;
                     default: /* Avoid compiler warnings.  */
                         abort();
@@ -4669,13 +4677,13 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
                         tcg_gen_shri_i32(tmp, tmp, shift);
                     switch (size) {
                     case 0:
-                        gen_aa32_st8(tmp, addr, get_mem_index(s));
+                        gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                         break;
                     case 1:
-                        gen_aa32_st16(tmp, addr, get_mem_index(s));
+                        gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                         break;
                     case 2:
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         break;
                     }
                     tcg_temp_free_i32(tmp);
@@ -7435,14 +7443,14 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
 
     switch (size) {
     case 0:
-        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
         break;
     case 1:
-        gen_aa32_ld16ua(tmp, addr, get_mem_index(s));
+        gen_aa32_ld16ua(s, tmp, addr, get_mem_index(s));
         break;
     case 2:
     case 3:
-        gen_aa32_ld32ua(tmp, addr, get_mem_index(s));
+        gen_aa32_ld32ua(s, tmp, addr, get_mem_index(s));
         break;
     default:
         abort();
@@ -7453,7 +7461,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
         TCGv_i32 tmp3 = tcg_temp_new_i32();
 
         tcg_gen_addi_i32(tmp2, addr, 4);
-        gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
+        gen_aa32_ld32u(s, tmp3, tmp2, get_mem_index(s));
         tcg_temp_free_i32(tmp2);
         tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
         store_reg(s, rt2, tmp3);
@@ -7504,14 +7512,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     tmp = tcg_temp_new_i32();
     switch (size) {
     case 0:
-        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
         break;
     case 1:
-        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
         break;
     case 2:
     case 3:
-        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
         break;
     default:
         abort();
@@ -7522,7 +7530,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
         TCGv_i32 tmp2 = tcg_temp_new_i32();
         TCGv_i32 tmp3 = tcg_temp_new_i32();
         tcg_gen_addi_i32(tmp2, addr, 4);
-        gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
+        gen_aa32_ld32u(s, tmp3, tmp2, get_mem_index(s));
         tcg_temp_free_i32(tmp2);
         tcg_gen_concat_i32_i64(val64, tmp, tmp3);
         tcg_temp_free_i32(tmp3);
@@ -7537,14 +7545,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     tmp = load_reg(s, rt);
     switch (size) {
     case 0:
-        gen_aa32_st8(tmp, addr, get_mem_index(s));
+        gen_aa32_st8(s, tmp, addr, get_mem_index(s));
         break;
     case 1:
-        gen_aa32_st16(tmp, addr, get_mem_index(s));
+        gen_aa32_st16(s, tmp, addr, get_mem_index(s));
         break;
     case 2:
     case 3:
-        gen_aa32_st32(tmp, addr, get_mem_index(s));
+        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
         break;
     default:
         abort();
@@ -7553,7 +7561,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     if (size == 3) {
         tcg_gen_addi_i32(addr, addr, 4);
         tmp = load_reg(s, rt2);
-        gen_aa32_st32(tmp, addr, get_mem_index(s));
+        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
         tcg_temp_free_i32(tmp);
     }
     tcg_gen_movi_i32(cpu_R[rd], 0);
@@ -7600,11 +7608,11 @@ static void gen_srs(DisasContext *s,
     }
     tcg_gen_addi_i32(addr, addr, offset);
     tmp = load_reg(s, 14);
-    gen_aa32_st32(tmp, addr, get_mem_index(s));
+    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
     tcg_temp_free_i32(tmp);
     tmp = load_cpu_field(spsr);
     tcg_gen_addi_i32(addr, addr, 4);
-    gen_aa32_st32(tmp, addr, get_mem_index(s));
+    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
     tcg_temp_free_i32(tmp);
     if (writeback) {
         switch (amode) {
@@ -7765,10 +7773,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                 tcg_gen_addi_i32(addr, addr, offset);
             /* Load PC into tmp and CPSR into tmp2.  */
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
             tcg_gen_addi_i32(addr, addr, 4);
             tmp2 = tcg_temp_new_i32();
-            gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
             if (insn & (1 << 21)) {
                 /* Base writeback.  */
                 switch (i) {
@@ -8384,13 +8392,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                                 tmp = tcg_temp_new_i32();
                                 switch (op1) {
                                 case 0: /* lda */
-                                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                                    gen_aa32_ld32u(s, tmp, addr,
+                                                   get_mem_index(s));
                                     break;
                                 case 2: /* ldab */
-                                    gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                                    gen_aa32_ld8u(s, tmp, addr,
+                                                  get_mem_index(s));
                                     break;
                                 case 3: /* ldah */
-                                    gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                                    gen_aa32_ld16u(s, tmp, addr,
+                                                   get_mem_index(s));
                                     break;
                                 default:
                                     abort();
@@ -8401,13 +8412,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                                 tmp = load_reg(s, rm);
                                 switch (op1) {
                                 case 0: /* stl */
-                                    gen_aa32_st32(tmp, addr, get_mem_index(s));
+                                    gen_aa32_st32(s, tmp, addr,
+                                                  get_mem_index(s));
                                     break;
                                 case 2: /* stlb */
-                                    gen_aa32_st8(tmp, addr, get_mem_index(s));
+                                    gen_aa32_st8(s, tmp, addr,
+                                                 get_mem_index(s));
                                     break;
                                 case 3: /* stlh */
-                                    gen_aa32_st16(tmp, addr, get_mem_index(s));
+                                    gen_aa32_st16(s, tmp, addr,
+                                                  get_mem_index(s));
                                     break;
                                 default:
                                     abort();
@@ -8462,11 +8476,11 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                         tmp = load_reg(s, rm);
                         tmp2 = tcg_temp_new_i32();
                         if (insn & (1 << 22)) {
-                            gen_aa32_ld8u(tmp2, addr, get_mem_index(s));
-                            gen_aa32_st8(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld8u(s, tmp2, addr, get_mem_index(s));
+                            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                         } else {
-                            gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
-                            gen_aa32_st32(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
+                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         }
                         tcg_temp_free_i32(tmp);
                         tcg_temp_free_i32(addr);
@@ -8501,20 +8515,20 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                     if (!load) {
                         /* store */
                         tmp = load_reg(s, rd);
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         tcg_temp_free_i32(tmp);
                         tcg_gen_addi_i32(addr, addr, 4);
                         tmp = load_reg(s, rd + 1);
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         tcg_temp_free_i32(tmp);
                     } else {
                         /* load */
                         tmp = tcg_temp_new_i32();
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                         store_reg(s, rd, tmp);
                         tcg_gen_addi_i32(addr, addr, 4);
                         tmp = tcg_temp_new_i32();
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                         rd++;
                     }
                     address_offset = -4;
@@ -8523,20 +8537,20 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                     tmp = tcg_temp_new_i32();
                     switch (sh) {
                     case 1:
-                        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                         break;
                     case 2:
-                        gen_aa32_ld8s(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
                         break;
                     default:
                     case 3:
-                        gen_aa32_ld16s(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
                         break;
                     }
                 } else {
                     /* store */
                     tmp = load_reg(s, rd);
-                    gen_aa32_st16(tmp, addr, get_mem_index(s));
+                    gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                     tcg_temp_free_i32(tmp);
                 }
                 /* Perform base writeback before the loaded value to
@@ -8889,17 +8903,17 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                 /* load */
                 tmp = tcg_temp_new_i32();
                 if (insn & (1 << 22)) {
-                    gen_aa32_ld8u(tmp, tmp2, i);
+                    gen_aa32_ld8u(s, tmp, tmp2, i);
                 } else {
-                    gen_aa32_ld32u(tmp, tmp2, i);
+                    gen_aa32_ld32u(s, tmp, tmp2, i);
                 }
             } else {
                 /* store */
                 tmp = load_reg(s, rd);
                 if (insn & (1 << 22)) {
-                    gen_aa32_st8(tmp, tmp2, i);
+                    gen_aa32_st8(s, tmp, tmp2, i);
                 } else {
-                    gen_aa32_st32(tmp, tmp2, i);
+                    gen_aa32_st32(s, tmp, tmp2, i);
                 }
                 tcg_temp_free_i32(tmp);
             }
@@ -8972,7 +8986,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                         if (is_load) {
                             /* load */
                             tmp = tcg_temp_new_i32();
-                            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                             if (user) {
                                 tmp2 = tcg_const_i32(i);
                                 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
@@ -8999,7 +9013,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                             } else {
                                 tmp = load_reg(s, i);
                             }
-                            gen_aa32_st32(tmp, addr, get_mem_index(s));
+                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                             tcg_temp_free_i32(tmp);
                         }
                         j++;
@@ -9266,20 +9280,20 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                 if (insn & (1 << 20)) {
                     /* ldrd */
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     store_reg(s, rs, tmp);
                     tcg_gen_addi_i32(addr, addr, 4);
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     store_reg(s, rd, tmp);
                 } else {
                     /* strd */
                     tmp = load_reg(s, rs);
-                    gen_aa32_st32(tmp, addr, get_mem_index(s));
+                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                     tcg_temp_free_i32(tmp);
                     tcg_gen_addi_i32(addr, addr, 4);
                     tmp = load_reg(s, rd);
-                    gen_aa32_st32(tmp, addr, get_mem_index(s));
+                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                     tcg_temp_free_i32(tmp);
                 }
                 if (insn & (1 << 21)) {
@@ -9317,11 +9331,11 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                     tcg_gen_add_i32(addr, addr, tmp);
                     tcg_temp_free_i32(tmp);
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                 } else { /* tbb */
                     tcg_temp_free_i32(tmp);
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                 }
                 tcg_temp_free_i32(addr);
                 tcg_gen_shli_i32(tmp, tmp, 1);
@@ -9358,13 +9372,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                         tmp = tcg_temp_new_i32();
                         switch (op) {
                         case 0: /* ldab */
-                            gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                             break;
                         case 1: /* ldah */
-                            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                             break;
                         case 2: /* lda */
-                            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                             break;
                         default:
                             abort();
@@ -9374,13 +9388,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                         tmp = load_reg(s, rs);
                         switch (op) {
                         case 0: /* stlb */
-                            gen_aa32_st8(tmp, addr, get_mem_index(s));
+                            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                             break;
                         case 1: /* stlh */
-                            gen_aa32_st16(tmp, addr, get_mem_index(s));
+                            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                             break;
                         case 2: /* stl */
-                            gen_aa32_st32(tmp, addr, get_mem_index(s));
+                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                             break;
                         default:
                             abort();
@@ -9408,10 +9422,10 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                         tcg_gen_addi_i32(addr, addr, -8);
                     /* Load PC into tmp and CPSR into tmp2.  */
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     tcg_gen_addi_i32(addr, addr, 4);
                     tmp2 = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
                     if (insn & (1 << 21)) {
                         /* Base writeback.  */
                         if (insn & (1 << 24)) {
@@ -9450,7 +9464,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                     if (insn & (1 << 20)) {
                         /* Load.  */
                         tmp = tcg_temp_new_i32();
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                         if (i == 15) {
                             gen_bx(s, tmp);
                         } else if (i == rn) {
@@ -9462,7 +9476,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                     } else {
                         /* Store.  */
                         tmp = load_reg(s, i);
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         tcg_temp_free_i32(tmp);
                     }
                     tcg_gen_addi_i32(addr, addr, 4);
@@ -10392,19 +10406,19 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
             tmp = tcg_temp_new_i32();
             switch (op) {
             case 0:
-                gen_aa32_ld8u(tmp, addr, memidx);
+                gen_aa32_ld8u(s, tmp, addr, memidx);
                 break;
             case 4:
-                gen_aa32_ld8s(tmp, addr, memidx);
+                gen_aa32_ld8s(s, tmp, addr, memidx);
                 break;
             case 1:
-                gen_aa32_ld16u(tmp, addr, memidx);
+                gen_aa32_ld16u(s, tmp, addr, memidx);
                 break;
             case 5:
-                gen_aa32_ld16s(tmp, addr, memidx);
+                gen_aa32_ld16s(s, tmp, addr, memidx);
                 break;
             case 2:
-                gen_aa32_ld32u(tmp, addr, memidx);
+                gen_aa32_ld32u(s, tmp, addr, memidx);
                 break;
             default:
                 tcg_temp_free_i32(tmp);
@@ -10421,13 +10435,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
             tmp = load_reg(s, rs);
             switch (op) {
             case 0:
-                gen_aa32_st8(tmp, addr, memidx);
+                gen_aa32_st8(s, tmp, addr, memidx);
                 break;
             case 1:
-                gen_aa32_st16(tmp, addr, memidx);
+                gen_aa32_st16(s, tmp, addr, memidx);
                 break;
             case 2:
-                gen_aa32_st32(tmp, addr, memidx);
+                gen_aa32_st32(s, tmp, addr, memidx);
                 break;
             default:
                 tcg_temp_free_i32(tmp);
@@ -10564,7 +10578,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
             addr = tcg_temp_new_i32();
             tcg_gen_movi_i32(addr, val);
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
             tcg_temp_free_i32(addr);
             store_reg(s, rd, tmp);
             break;
@@ -10767,28 +10781,28 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 
         switch (op) {
         case 0: /* str */
-            gen_aa32_st32(tmp, addr, get_mem_index(s));
+            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
             break;
         case 1: /* strh */
-            gen_aa32_st16(tmp, addr, get_mem_index(s));
+            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
             break;
         case 2: /* strb */
-            gen_aa32_st8(tmp, addr, get_mem_index(s));
+            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
             break;
         case 3: /* ldrsb */
-            gen_aa32_ld8s(tmp, addr, get_mem_index(s));
+            gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
             break;
         case 4: /* ldr */
-            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
             break;
         case 5: /* ldrh */
-            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
             break;
         case 6: /* ldrb */
-            gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
             break;
         case 7: /* ldrsh */
-            gen_aa32_ld16s(tmp, addr, get_mem_index(s));
+            gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
             break;
         }
         if (op >= 3) { /* load */
@@ -10810,12 +10824,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         if (insn & (1 << 11)) {
             /* load */
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
             store_reg(s, rd, tmp);
         } else {
             /* store */
             tmp = load_reg(s, rd);
-            gen_aa32_st32(tmp, addr, get_mem_index(s));
+            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
             tcg_temp_free_i32(tmp);
         }
         tcg_temp_free_i32(addr);
@@ -10832,12 +10846,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         if (insn & (1 << 11)) {
             /* load */
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
             store_reg(s, rd, tmp);
         } else {
             /* store */
             tmp = load_reg(s, rd);
-            gen_aa32_st8(tmp, addr, get_mem_index(s));
+            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
             tcg_temp_free_i32(tmp);
         }
         tcg_temp_free_i32(addr);
@@ -10854,12 +10868,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         if (insn & (1 << 11)) {
             /* load */
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
             store_reg(s, rd, tmp);
         } else {
             /* store */
             tmp = load_reg(s, rd);
-            gen_aa32_st16(tmp, addr, get_mem_index(s));
+            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
             tcg_temp_free_i32(tmp);
         }
         tcg_temp_free_i32(addr);
@@ -10875,12 +10889,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         if (insn & (1 << 11)) {
             /* load */
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
             store_reg(s, rd, tmp);
         } else {
             /* store */
             tmp = load_reg(s, rd);
-            gen_aa32_st32(tmp, addr, get_mem_index(s));
+            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
             tcg_temp_free_i32(tmp);
         }
         tcg_temp_free_i32(addr);
@@ -10948,12 +10962,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                     if (insn & (1 << 11)) {
                         /* pop */
                         tmp = tcg_temp_new_i32();
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                         store_reg(s, i, tmp);
                     } else {
                         /* push */
                         tmp = load_reg(s, i);
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         tcg_temp_free_i32(tmp);
                     }
                     /* advance to the next address.  */
@@ -10965,13 +10979,13 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                 if (insn & (1 << 11)) {
                     /* pop pc */
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     /* don't set the pc until the rest of the instruction
                        has completed */
                 } else {
                     /* push lr */
                     tmp = load_reg(s, 14);
-                    gen_aa32_st32(tmp, addr, get_mem_index(s));
+                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                     tcg_temp_free_i32(tmp);
                 }
                 tcg_gen_addi_i32(addr, addr, 4);
@@ -11101,7 +11115,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                 if (insn & (1 << 11)) {
                     /* load */
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     if (i == rn) {
                         loaded_var = tmp;
                     } else {
@@ -11110,7 +11124,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                 } else {
                     /* store */
                     tmp = load_reg(s, i);
-                    gen_aa32_st32(tmp, addr, get_mem_index(s));
+                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                     tcg_temp_free_i32(tmp);
                 }
                 /* advance to the next address */
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 06/17] target-arm: introduce disas flag for endianness
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (4 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 05/17] target-arm: pass DisasContext to gen_aa32_ld*/st* Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 16:08   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 07/17] target-arm: a64: Add endianness support Peter Crosthwaite
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Paolo Bonzini <pbonzini@redhat.com>

Introduce a disas flag for setting the CPU data endianness. This allows
control of the endianness from the CPU state rather than hard-coding it
to TARGET_WORDS_BIGENDIAN.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[ PC changes:
  * Split off as new patch from original:
        "target-arm: introduce tbflag for CPSR.E"
  * Wrote commit message from scratch
]
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---

 target-arm/translate-a64.c |  1 +
 target-arm/translate.c     | 39 ++++++++++++++++++++++++---------------
 target-arm/translate.h     |  1 +
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 14e8131..d826b92 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -11033,6 +11033,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
                                !arm_el_is_aa64(env, 3);
     dc->thumb = 0;
     dc->bswap_code = 0;
+    dc->mo_endianness = MO_TE;
     dc->condexec_mask = 0;
     dc->condexec_cond = 0;
     dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 55ecca5..e1679d3 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -927,26 +927,30 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,      \
                                      TCGv_i32 addr, int index)           \
 {                                                                        \
-    tcg_gen_qemu_ld_i32(val, addr, index, (OPC));                        \
+    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
+    tcg_gen_qemu_ld_i32(val, addr, index, opc);                          \
 }
 
 #define DO_GEN_ST(SUFF, OPC)                                             \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,      \
                                      TCGv_i32 addr, int index)           \
 {                                                                        \
-    tcg_gen_qemu_st_i32(val, addr, index, (OPC));                        \
+    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
+    tcg_gen_qemu_st_i32(val, addr, index, opc);                          \
 }
 
 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
                                  TCGv_i32 addr, int index)
 {
-    tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
+    TCGMemOp opc = MO_Q | s->mo_endianness;
+    tcg_gen_qemu_ld_i64(val, addr, index, opc);
 }
 
 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
                                  TCGv_i32 addr, int index)
 {
-    tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
+    TCGMemOp opc = MO_Q | s->mo_endianness;
+    tcg_gen_qemu_st_i64(val, addr, index, opc);
 }
 
 #else
@@ -955,9 +959,10 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,      \
                                      TCGv_i32 addr, int index)           \
 {                                                                        \
+    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
     TCGv addr64 = tcg_temp_new();                                        \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
-    tcg_gen_qemu_ld_i32(val, addr64, index, OPC);                        \
+    tcg_gen_qemu_ld_i32(val, addr64, index, opc);                        \
     tcg_temp_free(addr64);                                               \
 }
 
@@ -965,27 +970,30 @@ static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,      \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,      \
                                      TCGv_i32 addr, int index)           \
 {                                                                        \
+    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
     TCGv addr64 = tcg_temp_new();                                        \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
-    tcg_gen_qemu_st_i32(val, addr64, index, OPC);                        \
+    tcg_gen_qemu_st_i32(val, addr64, index, opc);                        \
     tcg_temp_free(addr64);                                               \
 }
 
 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
                                  TCGv_i32 addr, int index)
 {
+    TCGMemOp opc = MO_Q | s->mo_endianness;
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
-    tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
+    tcg_gen_qemu_ld_i64(val, addr64, index, opc);
     tcg_temp_free(addr64);
 }
 
 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
                                  TCGv_i32 addr, int index)
 {
+    TCGMemOp opc = MO_Q | s->mo_endianness;
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
-    tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
+    tcg_gen_qemu_st_i64(val, addr64, index, opc);
     tcg_temp_free(addr64);
 }
 
@@ -993,15 +1001,15 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
 
 DO_GEN_LD(8s, MO_SB)
 DO_GEN_LD(8u, MO_UB)
-DO_GEN_LD(16s, MO_TESW)
-DO_GEN_LD(16u, MO_TEUW)
-DO_GEN_LD(32u, MO_TEUL)
+DO_GEN_LD(16s, MO_SW)
+DO_GEN_LD(16u, MO_UW)
+DO_GEN_LD(32u, MO_UL)
 /* 'a' variants include an alignment check */
-DO_GEN_LD(16ua, MO_TEUW | MO_ALIGN)
-DO_GEN_LD(32ua, MO_TEUL | MO_ALIGN)
+DO_GEN_LD(16ua, MO_UW | MO_ALIGN)
+DO_GEN_LD(32ua, MO_UL | MO_ALIGN)
 DO_GEN_ST(8, MO_UB)
-DO_GEN_ST(16, MO_TEUW)
-DO_GEN_ST(32, MO_TEUL)
+DO_GEN_ST(16, MO_UW)
+DO_GEN_ST(32, MO_UL)
 
 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
 {
@@ -11266,6 +11274,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
                                !arm_el_is_aa64(env, 3);
     dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
     dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
+    dc->mo_endianness = MO_TE;
     dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
     dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
     dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 53ef971..95c3b94 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -17,6 +17,7 @@ typedef struct DisasContext {
     int singlestep_enabled;
     int thumb;
     int bswap_code;
+    TCGMemOp mo_endianness;
 #if !defined(CONFIG_USER_ONLY)
     int user;
 #endif
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 07/17] target-arm: a64: Add endianness support
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (5 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 06/17] target-arm: introduce disas flag for endianness Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 16:09   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header Peter Crosthwaite
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>

Set the dc->mo_endianness flag for AA64 and use it in all ldst ops.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---

 target-arm/translate-a64.c | 49 ++++++++++++++++++++++++++++------------------
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index d826b92..59026b6 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -726,7 +726,7 @@ static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source,
                              TCGv_i64 tcg_addr, int size, int memidx)
 {
     g_assert(size <= 3);
-    tcg_gen_qemu_st_i64(source, tcg_addr, memidx, MO_TE + size);
+    tcg_gen_qemu_st_i64(source, tcg_addr, memidx, s->mo_endianness + size);
 }
 
 static void do_gpr_st(DisasContext *s, TCGv_i64 source,
@@ -741,7 +741,7 @@ static void do_gpr_st(DisasContext *s, TCGv_i64 source,
 static void do_gpr_ld_memidx(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
                              int size, bool is_signed, bool extend, int memidx)
 {
-    TCGMemOp memop = MO_TE + size;
+    TCGMemOp memop = s->mo_endianness + size;
 
     g_assert(size <= 3);
 
@@ -773,13 +773,18 @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
     TCGv_i64 tmp = tcg_temp_new_i64();
     tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
     if (size < 4) {
-        tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
+        tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s),
+                            s->mo_endianness + size);
     } else {
+        bool be = s->mo_endianness == MO_BE;
         TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
-        tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
+
+        tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
+        tcg_gen_qemu_st_i64(tmp, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
+                            s->mo_endianness | MO_Q);
         tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
-        tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
-        tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
+        tcg_gen_qemu_st_i64(tmp, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
+                            s->mo_endianness | MO_Q);
         tcg_temp_free_i64(tcg_hiaddr);
     }
 
@@ -796,17 +801,21 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
     TCGv_i64 tmphi;
 
     if (size < 4) {
-        TCGMemOp memop = MO_TE + size;
+        TCGMemOp memop = s->mo_endianness + size;
         tmphi = tcg_const_i64(0);
         tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
     } else {
+        bool be = s->mo_endianness == MO_BE;
         TCGv_i64 tcg_hiaddr;
+
         tmphi = tcg_temp_new_i64();
         tcg_hiaddr = tcg_temp_new_i64();
 
-        tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
-        tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
+        tcg_gen_qemu_ld_i64(tmplo, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
+                            s->mo_endianness | MO_Q);
+        tcg_gen_qemu_ld_i64(tmphi, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
+                            s->mo_endianness | MO_Q);
         tcg_temp_free_i64(tcg_hiaddr);
     }
 
@@ -945,7 +954,7 @@ static void clear_vec_high(DisasContext *s, int rd)
 static void do_vec_st(DisasContext *s, int srcidx, int element,
                       TCGv_i64 tcg_addr, int size)
 {
-    TCGMemOp memop = MO_TE + size;
+    TCGMemOp memop = s->mo_endianness + size;
     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 
     read_vec_element(s, tcg_tmp, srcidx, element, size);
@@ -958,7 +967,7 @@ static void do_vec_st(DisasContext *s, int srcidx, int element,
 static void do_vec_ld(DisasContext *s, int destidx, int element,
                       TCGv_i64 tcg_addr, int size)
 {
-    TCGMemOp memop = MO_TE + size;
+    TCGMemOp memop = s->mo_endianness + size;
     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 
     tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
@@ -1703,7 +1712,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
                                TCGv_i64 addr, int size, bool is_pair)
 {
     TCGv_i64 tmp = tcg_temp_new_i64();
-    TCGMemOp memop = MO_TE + size;
+    TCGMemOp memop = s->mo_endianness + size;
 
     g_assert(size <= 3);
     tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
@@ -1765,7 +1774,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
 
     tmp = tcg_temp_new_i64();
-    tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), MO_TE + size);
+    tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), s->mo_endianness + size);
     tcg_gen_brcond_i64(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
     tcg_temp_free_i64(tmp);
 
@@ -1774,7 +1783,8 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
         TCGv_i64 tmphi = tcg_temp_new_i64();
 
         tcg_gen_addi_i64(addrhi, addr, 1 << size);
-        tcg_gen_qemu_ld_i64(tmphi, addrhi, get_mem_index(s), MO_TE + size);
+        tcg_gen_qemu_ld_i64(tmphi, addrhi, get_mem_index(s),
+                            s->mo_endianness + size);
         tcg_gen_brcond_i64(TCG_COND_NE, tmphi, cpu_exclusive_high, fail_label);
 
         tcg_temp_free_i64(tmphi);
@@ -1782,13 +1792,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     }
 
     /* We seem to still have the exclusive monitor, so do the store */
-    tcg_gen_qemu_st_i64(cpu_reg(s, rt), addr, get_mem_index(s), MO_TE + size);
+    tcg_gen_qemu_st_i64(cpu_reg(s, rt), addr, get_mem_index(s),
+                        s->mo_endianness + size);
     if (is_pair) {
         TCGv_i64 addrhi = tcg_temp_new_i64();
 
         tcg_gen_addi_i64(addrhi, addr, 1 << size);
         tcg_gen_qemu_st_i64(cpu_reg(s, rt2), addrhi,
-                            get_mem_index(s), MO_TE + size);
+                            get_mem_index(s), s->mo_endianness + size);
         tcg_temp_free_i64(addrhi);
     }
 
@@ -2603,7 +2614,7 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
             TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 
             tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
-                                get_mem_index(s), MO_TE + scale);
+                                get_mem_index(s), s->mo_endianness + scale);
             switch (scale) {
             case 0:
                 mulconst = 0x0101010101010101ULL;
@@ -2633,9 +2644,9 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
         } else {
             /* Load/store one element per register */
             if (is_load) {
-                do_vec_ld(s, rt, index, tcg_addr, MO_TE + scale);
+                do_vec_ld(s, rt, index, tcg_addr, s->mo_endianness + scale);
             } else {
-                do_vec_st(s, rt, index, tcg_addr, MO_TE + scale);
+                do_vec_st(s, rt, index, tcg_addr, s->mo_endianness + scale);
             }
         }
         tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (6 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 07/17] target-arm: a64: Add endianness support Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-18 21:52   ` Alistair Francis
  2016-01-19 16:11   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 09/17] target-arm: introduce tbflag for endianness Peter Crosthwaite
                   ` (10 subsequent siblings)
  18 siblings, 2 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>

There is a CPU data endianness test that is used to drive the
virtio_big_endian test.

Move this up to the header so it can be more generally used for endian
tests. The KVM specific cpu_syncronize_state call is left behind in the
virtio specific function.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---

 target-arm/cpu.c | 19 +++----------------
 target-arm/cpu.h | 19 +++++++++++++++++++
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 35a1f12..d3b73bf 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -368,26 +368,13 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
 #endif
 }
 
-static bool arm_cpu_is_big_endian(CPUState *cs)
+static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
 {
     ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
-    int cur_el;
 
     cpu_synchronize_state(cs);
-
-    /* In 32bit guest endianness is determined by looking at CPSR's E bit */
-    if (!is_a64(env)) {
-        return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
-    }
-
-    cur_el = arm_current_el(env);
-
-    if (cur_el == 0) {
-        return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
-    }
-
-    return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
+    return arm_cpu_is_big_endian(env);
 }
 
 #endif
@@ -1420,7 +1407,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_unaligned_access = arm_cpu_do_unaligned_access;
     cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
     cc->vmsd = &vmstate_arm_cpu;
-    cc->virtio_is_big_endian = arm_cpu_is_big_endian;
+    cc->virtio_is_big_endian = arm_cpu_virtio_is_big_endian;
 #endif
     cc->gdb_num_core_regs = 26;
     cc->gdb_core_xml_file = "arm-core.xml";
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f83070a..54675c7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1795,6 +1795,25 @@ static inline bool arm_singlestep_active(CPUARMState *env)
         && arm_generate_debug_exceptions(env);
 }
 
+/* Return true if the processor is in big-endian mode. */
+static bool arm_cpu_is_big_endian(CPUARMState *env)
+{
+    int cur_el;
+
+    /* In 32bit endianness is determined by looking at CPSR's E bit */
+    if (!is_a64(env)) {
+        return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
+    }
+
+    cur_el = arm_current_el(env);
+
+    if (cur_el == 0) {
+        return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
+    }
+
+    return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
+}
+
 #include "exec/cpu-all.h"
 
 /* Bit usage in the TB flags field: bit 31 indicates whether we are
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 09/17] target-arm: introduce tbflag for endianness
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (7 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 16:15   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 10/17] target-arm: implement setend Peter Crosthwaite
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>

Introduce a tbflags for endianness, set based upon the CPUs current
endianness. This in turn propagates through to the disas endianness
flag.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---

 target-arm/cpu.h           | 7 +++++++
 target-arm/translate-a64.c | 2 +-
 target-arm/translate.c     | 2 +-
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 54675c7..74048d1 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1857,6 +1857,8 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
  */
 #define ARM_TBFLAG_NS_SHIFT         19
 #define ARM_TBFLAG_NS_MASK          (1 << ARM_TBFLAG_NS_SHIFT)
+#define ARM_TBFLAG_MOE_SHIFT        20
+#define ARM_TBFLAG_MOE_MASK         (1 << ARM_TBFLAG_MOE_SHIFT)
 
 /* Bit usage when in AArch64 state: currently we have no A64 specific bits */
 
@@ -1887,6 +1889,8 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
     (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
 #define ARM_TBFLAG_NS(F) \
     (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
+#define ARM_TBFLAG_MOE(F) \
+    (((F) & ARM_TBFLAG_MOE_MASK) >> ARM_TBFLAG_MOE_SHIFT)
 
 /* Return the exception level to which FP-disabled exceptions should
  * be taken, or 0 if FP is enabled.
@@ -2018,6 +2022,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
             }
         }
     }
+    if (arm_cpu_is_big_endian(env)) {
+        *flags |= ARM_TBFLAG_MOE_MASK;
+    }
     *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
 
     *cs_base = 0;
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 59026b6..db68662 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -11044,7 +11044,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
                                !arm_el_is_aa64(env, 3);
     dc->thumb = 0;
     dc->bswap_code = 0;
-    dc->mo_endianness = MO_TE;
+    dc->mo_endianness = ARM_TBFLAG_MOE(tb->flags) ? MO_BE : MO_LE;
     dc->condexec_mask = 0;
     dc->condexec_cond = 0;
     dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index e1679d3..cb925ef 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -11274,7 +11274,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
                                !arm_el_is_aa64(env, 3);
     dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
     dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
-    dc->mo_endianness = MO_TE;
+    dc->mo_endianness = ARM_TBFLAG_MOE(tb->flags) ? MO_BE : MO_LE;
     dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
     dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
     dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 10/17] target-arm: implement setend
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (8 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 09/17] target-arm: introduce tbflag for endianness Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 16:29   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 11/17] linux-user: arm: pass env to get_user_code_* Peter Crosthwaite
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Paolo Bonzini <pbonzini@redhat.com>

Since this is not a high-performance path, just use a helper to
flip the E bit and force a lookup in the hash table since the
flags have changed.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 target-arm/helper.h    |  1 +
 target-arm/op_helper.c |  5 +++++
 target-arm/translate.c | 16 ++++++++--------
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/target-arm/helper.h b/target-arm/helper.h
index c2a85c7..2315a9c 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -48,6 +48,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
                    i32, i32, i32, i32)
 DEF_HELPER_2(exception_internal, void, env, i32)
 DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
+DEF_HELPER_1(setend, void, env)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(wfe, void, env)
 DEF_HELPER_1(yield, void, env)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index e42d287..2a4bc67 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -295,6 +295,11 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
     return res;
 }
 
+void HELPER(setend)(CPUARMState *env)
+{
+    env->uncached_cpsr ^= CPSR_E;
+}
+
 /* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
  * The function returns the target EL (1-3) if the instruction is to be trapped;
  * otherwise it returns 0 indicating it is not trapped.
diff --git a/target-arm/translate.c b/target-arm/translate.c
index cb925ef..192a5d6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7726,10 +7726,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
         if ((insn & 0x0ffffdff) == 0x01010000) {
             ARCH(6);
             /* setend */
-            if (((insn >> 9) & 1) != s->bswap_code) {
-                /* Dynamic endianness switching not implemented. */
-                qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
-                goto illegal_op;
+            if (((insn >> 9) & 1) != !!(s->mo_endianness == MO_BE)) {
+                gen_helper_setend(cpu_env);
+                gen_set_pc_im(s, s->pc);
+                s->is_jmp = DISAS_JUMP;
             }
             return;
         } else if ((insn & 0x0fffff00) == 0x057ff000) {
@@ -11064,10 +11064,10 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
             case 2:
                 /* setend */
                 ARCH(6);
-                if (((insn >> 3) & 1) != s->bswap_code) {
-                    /* Dynamic endianness switching not implemented. */
-                    qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
-                    goto illegal_op;
+                if (((insn >> 3) & 1) != !!(s->mo_endianness == MO_BE)) {
+                    gen_helper_setend(cpu_env);
+                    gen_set_pc_im(s, s->pc);
+                    s->is_jmp = DISAS_JUMP;
                 }
                 break;
             case 3:
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 11/17] linux-user: arm: pass env to get_user_code_*
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (9 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 10/17] target-arm: implement setend Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 12/17] target-arm: implement SCTLR.B, drop bswap_code Peter Crosthwaite
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Paolo Bonzini <pbonzini@redhat.com>

This matches the idiom used by get_user_data_* later in the series,
and will help when bswap_code will be replaced by SCTLR.B.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 linux-user/main.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 8348ddc..2157774 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -439,17 +439,17 @@ void cpu_loop(CPUX86State *env)
 
 #ifdef TARGET_ARM
 
-#define get_user_code_u32(x, gaddr, doswap)             \
+#define get_user_code_u32(x, gaddr, env)                \
     ({ abi_long __r = get_user_u32((x), (gaddr));       \
-        if (!__r && (doswap)) {                         \
+        if (!__r && (env)->bswap_code) {                \
             (x) = bswap32(x);                           \
         }                                               \
         __r;                                            \
     })
 
-#define get_user_code_u16(x, gaddr, doswap)             \
+#define get_user_code_u16(x, gaddr, env)                \
     ({ abi_long __r = get_user_u16((x), (gaddr));       \
-        if (!__r && (doswap)) {                         \
+        if (!__r && (env)->bswap_code) {                \
             (x) = bswap16(x);                           \
         }                                               \
         __r;                                            \
@@ -732,7 +732,7 @@ void cpu_loop(CPUARMState *env)
                 /* we handle the FPU emulation here, as Linux */
                 /* we get the opcode */
                 /* FIXME - what to do if get_user() fails? */
-                get_user_code_u32(opcode, env->regs[15], env->bswap_code);
+                get_user_code_u32(opcode, env->regs[15], env);
 
                 rc = EmulateAll(opcode, &ts->fpa, env);
                 if (rc == 0) { /* illegal instruction */
@@ -802,25 +802,23 @@ void cpu_loop(CPUARMState *env)
                 if (trapnr == EXCP_BKPT) {
                     if (env->thumb) {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_code_u16(insn, env->regs[15], env->bswap_code);
+                        get_user_code_u16(insn, env->regs[15], env);
                         n = insn & 0xff;
                         env->regs[15] += 2;
                     } else {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_code_u32(insn, env->regs[15], env->bswap_code);
+                        get_user_code_u32(insn, env->regs[15], env);
                         n = (insn & 0xf) | ((insn >> 4) & 0xff0);
                         env->regs[15] += 4;
                     }
                 } else {
                     if (env->thumb) {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_code_u16(insn, env->regs[15] - 2,
-                                          env->bswap_code);
+                        get_user_code_u16(insn, env->regs[15] - 2, env);
                         n = insn & 0xff;
                     } else {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_code_u32(insn, env->regs[15] - 4,
-                                          env->bswap_code);
+                        get_user_code_u32(insn, env->regs[15] - 4, env);
                         n = insn & 0xffffff;
                     }
                 }
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 12/17] target-arm: implement SCTLR.B, drop bswap_code
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (10 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 11/17] linux-user: arm: pass env to get_user_code_* Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 17:21   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 13/17] arm: linux-user: don't set CPSR.E in BE32 mode Peter Crosthwaite
                   ` (6 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Paolo Bonzini <pbonzini@redhat.com>

bswap_code is a CPU property of sorts ("is the iside endianness the
opposite way round to TARGET_WORDS_BIGENDIAN?") but it is not the
actual CPU state involved here which is SCTLR.B (set for BE32
binaries, clear for BE8).

Replace bswap_code with SCTLR.B, and pass that to arm_ld*_code.
The next patches will make data fetches honor both SCTLR.B and
CPSR.E appropriately.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[PC changes:
 * rebased on master (Jan 2016)
 * Dropped comment about CPSR.E being unimplemented
 * s/TARGET_USER_ONLY/CONFIG_USER_ONLY
 * Use bswap_code() for disas_set_info() instead of raw sctlr_b
]
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 linux-user/main.c          | 13 ++++++++-----
 target-arm/arm_ldst.h      |  8 ++++----
 target-arm/cpu.c           |  2 +-
 target-arm/cpu.h           | 47 ++++++++++++++++++++++++++++++++++++++--------
 target-arm/helper.c        |  8 ++++----
 target-arm/translate-a64.c |  6 +++---
 target-arm/translate.c     | 12 ++++++------
 target-arm/translate.h     |  2 +-
 8 files changed, 66 insertions(+), 32 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 2157774..d481458 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -441,7 +441,7 @@ void cpu_loop(CPUX86State *env)
 
 #define get_user_code_u32(x, gaddr, env)                \
     ({ abi_long __r = get_user_u32((x), (gaddr));       \
-        if (!__r && (env)->bswap_code) {                \
+        if (!__r && bswap_code(arm_sctlr_b(env))) {     \
             (x) = bswap32(x);                           \
         }                                               \
         __r;                                            \
@@ -449,7 +449,7 @@ void cpu_loop(CPUX86State *env)
 
 #define get_user_code_u16(x, gaddr, env)                \
     ({ abi_long __r = get_user_u16((x), (gaddr));       \
-        if (!__r && (env)->bswap_code) {                \
+        if (!__r && bswap_code(arm_sctlr_b(env))) {     \
             (x) = bswap16(x);                           \
         }                                               \
         __r;                                            \
@@ -4489,14 +4489,17 @@ int main(int argc, char **argv, char **envp)
             env->regs[i] = regs->uregs[i];
         }
 #ifdef TARGET_WORDS_BIGENDIAN
-        env->uncached_cpsr |= CPSR_E;
         env->cp15.sctlr_el[1] |= SCTLR_E0E;
-#endif
         /* Enable BE8.  */
         if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
             && (info->elf_flags & EF_ARM_BE8)) {
-            env->bswap_code = 1;
+            env->uncached_cpsr |= CPSR_E;
+        } else {
+            env->cp15.sctlr_el[1] |= SCTLR_B;
+            /* We model BE32 as regular BE, so set CPSR_E */
+            env->uncached_cpsr |= CPSR_E;
         }
+#endif
     }
 #elif defined(TARGET_UNICORE32)
     {
diff --git a/target-arm/arm_ldst.h b/target-arm/arm_ldst.h
index b1ece01..35c2c43 100644
--- a/target-arm/arm_ldst.h
+++ b/target-arm/arm_ldst.h
@@ -25,10 +25,10 @@
 
 /* Load an instruction and return it in the standard little-endian order */
 static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
-                                    bool do_swap)
+                                    bool sctlr_b)
 {
     uint32_t insn = cpu_ldl_code(env, addr);
-    if (do_swap) {
+    if (bswap_code(sctlr_b)) {
         return bswap32(insn);
     }
     return insn;
@@ -36,10 +36,10 @@ static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
 
 /* Ditto, for a halfword (Thumb) instruction */
 static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
-                                     bool do_swap)
+                                     bool sctlr_b)
 {
     uint16_t insn = cpu_lduw_code(env, addr);
-    if (do_swap) {
+    if (bswap_code(sctlr_b)) {
         return bswap16(insn);
     }
     return insn;
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index d3b73bf..cec5147 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -413,7 +413,7 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info)
     } else {
         info->print_insn = print_insn_arm;
     }
-    if (env->bswap_code) {
+    if (bswap_code(arm_sctlr_b(env))) {
 #ifdef TARGET_WORDS_BIGENDIAN
         info->endian = BFD_ENDIAN_LITTLE;
 #else
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 74048d1..3edd56b 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -478,9 +478,6 @@ typedef struct CPUARMState {
         uint32_t cregs[16];
     } iwmmxt;
 
-    /* For mixed endian mode.  */
-    bool bswap_code;
-
 #if defined(CONFIG_USER_ONLY)
     /* For usermode syscall translation.  */
     int eabi;
@@ -1795,6 +1792,19 @@ static inline bool arm_singlestep_active(CPUARMState *env)
         && arm_generate_debug_exceptions(env);
 }
 
+static inline bool arm_sctlr_b(CPUARMState *env)
+{
+    return
+        /* We need not implement SCTLR.ITD in user-mode emulation, so
+         * let linux-user ignore the fact that it conflicts with SCTLR_B.
+         * This lets people run BE32 binaries with "-cpu any".
+         */
+#ifndef CONFIG_USER_ONLY
+        !arm_feature(env, ARM_FEATURE_V7) &&
+#endif
+        (env->cp15.sctlr_el[1] & SCTLR_B) != 0;
+}
+
 /* Return true if the processor is in big-endian mode. */
 static bool arm_cpu_is_big_endian(CPUARMState *env)
 {
@@ -1844,8 +1854,8 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
 #define ARM_TBFLAG_VFPEN_MASK       (1 << ARM_TBFLAG_VFPEN_SHIFT)
 #define ARM_TBFLAG_CONDEXEC_SHIFT   8
 #define ARM_TBFLAG_CONDEXEC_MASK    (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
-#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
-#define ARM_TBFLAG_BSWAP_CODE_MASK  (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
+#define ARM_TBFLAG_SCTLR_B_SHIFT    16
+#define ARM_TBFLAG_SCTLR_B_MASK     (1 << ARM_TBFLAG_SCTLR_B_SHIFT)
 /* We store the bottom two bits of the CPAR as TB flags and handle
  * checks on the other bits at runtime
  */
@@ -1883,8 +1893,8 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
     (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
 #define ARM_TBFLAG_CONDEXEC(F) \
     (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
-#define ARM_TBFLAG_BSWAP_CODE(F) \
-    (((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
+#define ARM_TBFLAG_SCTLR_B(F) \
+    (((F) & ARM_TBFLAG_SCTLR_B_MASK) >> ARM_TBFLAG_SCTLR_B_SHIFT)
 #define ARM_TBFLAG_XSCALE_CPAR(F) \
     (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
 #define ARM_TBFLAG_NS(F) \
@@ -1892,6 +1902,27 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
 #define ARM_TBFLAG_MOE(F) \
     (((F) & ARM_TBFLAG_MOE_MASK) >> ARM_TBFLAG_MOE_SHIFT)
 
+static inline bool bswap_code(bool sctlr_b)
+{
+#ifdef CONFIG_USER_ONLY
+    /* BE8 (SCTLR.B = 0, TARGET_WORDS_BIGENDIAN = 1) is mixed endian.
+     * The invalid combination SCTLR.B=1/CPSR.E=1/TARGET_WORDS_BIGENDIAN=0
+     * would also end up as a mixed-endian mode with BE code, LE data.
+     */
+    return
+#ifdef TARGET_WORDS_BIGENDIAN
+        1 ^
+#endif
+        sctlr_b;
+#else
+    /* We do not implement BE32 mode for system-mode emulation, but
+     * anyway it would always do little-endian accesses with
+     * TARGET_WORDS_BIGENDIAN = 0.
+     */
+    return 0;
+#endif
+}
+
 /* Return the exception level to which FP-disabled exceptions should
  * be taken, or 0 if FP is enabled.
  */
@@ -1990,7 +2021,7 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
             | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
             | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
             | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
-            | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
+            | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
         if (!(access_secure_reg(env))) {
             *flags |= ARM_TBFLAG_NS_MASK;
         }
diff --git a/target-arm/helper.c b/target-arm/helper.c
index afac1b2..a69a82c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5452,7 +5452,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
     case EXCP_BKPT:
         if (semihosting_enabled()) {
             int nr;
-            nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
+            nr = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env)) & 0xff;
             if (nr == 0xab) {
                 env->regs[15] += 2;
                 qemu_log_mask(CPU_LOG_INT,
@@ -5767,10 +5767,10 @@ void arm_cpu_do_interrupt(CPUState *cs)
         if (semihosting_enabled()) {
             /* Check for semihosting interrupt.  */
             if (env->thumb) {
-                mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)
+                mask = arm_lduw_code(env, env->regs[15] - 2, arm_sctlr_b(env))
                     & 0xff;
             } else {
-                mask = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code)
+                mask = arm_ldl_code(env, env->regs[15] - 4, arm_sctlr_b(env))
                     & 0xffffff;
             }
             /* Only intercept calls from privileged modes, to provide some
@@ -5794,7 +5794,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
     case EXCP_BKPT:
         /* See if this is a semihosting syscall.  */
         if (env->thumb && semihosting_enabled()) {
-            mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
+            mask = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env)) & 0xff;
             if (mask == 0xab
                   && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
                 env->regs[15] += 2;
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index db68662..4fd266b 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -10978,7 +10978,7 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
 {
     uint32_t insn;
 
-    insn = arm_ldl_code(env, s->pc, s->bswap_code);
+    insn = arm_ldl_code(env, s->pc, s->sctlr_b);
     s->insn = insn;
     s->pc += 4;
 
@@ -11043,7 +11043,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
     dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
                                !arm_el_is_aa64(env, 3);
     dc->thumb = 0;
-    dc->bswap_code = 0;
+    dc->sctlr_b = 0;
     dc->mo_endianness = ARM_TBFLAG_MOE(tb->flags) ? MO_BE : MO_LE;
     dc->condexec_mask = 0;
     dc->condexec_cond = 0;
@@ -11230,7 +11230,7 @@ done_generating:
         qemu_log("----------------\n");
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
         log_target_disas(cs, pc_start, dc->pc - pc_start,
-                         4 | (dc->bswap_code << 1));
+                         4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
         qemu_log("\n");
     }
 #endif
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 192a5d6..44c3ac9 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9251,7 +9251,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
         /* Fall through to 32-bit decode.  */
     }
 
-    insn = arm_lduw_code(env, s->pc, s->bswap_code);
+    insn = arm_lduw_code(env, s->pc, s->sctlr_b);
     s->pc += 2;
     insn |= (uint32_t)insn_hw1 << 16;
 
@@ -10493,7 +10493,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         }
     }
 
-    insn = arm_lduw_code(env, s->pc, s->bswap_code);
+    insn = arm_lduw_code(env, s->pc, s->sctlr_b);
     s->pc += 2;
 
     switch (insn >> 12) {
@@ -11218,7 +11218,7 @@ static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
     }
 
     /* This must be a Thumb insn */
-    insn = arm_lduw_code(env, s->pc, s->bswap_code);
+    insn = arm_lduw_code(env, s->pc, s->sctlr_b);
 
     if ((insn >> 11) >= 0x1d) {
         /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
@@ -11273,7 +11273,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
     dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
                                !arm_el_is_aa64(env, 3);
     dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
-    dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
+    dc->sctlr_b = ARM_TBFLAG_SCTLR_B(tb->flags);
     dc->mo_endianness = ARM_TBFLAG_MOE(tb->flags) ? MO_BE : MO_LE;
     dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
     dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
@@ -11454,7 +11454,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
                 }
             }
         } else {
-            unsigned int insn = arm_ldl_code(env, dc->pc, dc->bswap_code);
+            unsigned int insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
             dc->pc += 4;
             disas_arm_insn(dc, insn);
         }
@@ -11611,7 +11611,7 @@ done_generating:
         qemu_log("----------------\n");
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
         log_target_disas(cs, pc_start, dc->pc - pc_start,
-                         dc->thumb | (dc->bswap_code << 1));
+                         dc->thumb | (dc->sctlr_b << 1));
         qemu_log("\n");
     }
 #endif
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 95c3b94..7d7f449 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -16,7 +16,7 @@ typedef struct DisasContext {
     struct TranslationBlock *tb;
     int singlestep_enabled;
     int thumb;
-    int bswap_code;
+    int sctlr_b;
     TCGMemOp mo_endianness;
 #if !defined(CONFIG_USER_ONLY)
     int user;
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 13/17] arm: linux-user: don't set CPSR.E in BE32 mode
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (11 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 12/17] target-arm: implement SCTLR.B, drop bswap_code Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 17:26   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 14/17] target-arm: implement BE32 mode in system emulation Peter Crosthwaite
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

Don't set CPSR.E for BE32 linux-user mode. As linux-user mode models
BE32, using normal BE (and system mode will not), a special case is
needed for user-mode where if sctlr.b is set, the CPU identifies as BE.

Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 linux-user/main.c |  2 --
 target-arm/cpu.h  | 12 +++++++++++-
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index d481458..60375fb 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4496,8 +4496,6 @@ int main(int argc, char **argv, char **envp)
             env->uncached_cpsr |= CPSR_E;
         } else {
             env->cp15.sctlr_el[1] |= SCTLR_B;
-            /* We model BE32 as regular BE, so set CPSR_E */
-            env->uncached_cpsr |= CPSR_E;
         }
 #endif
     }
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 3edd56b..96b1e99 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1812,7 +1812,17 @@ static bool arm_cpu_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 user mode, BE32 data accesses are just modelled as
+             * regular BE access. In system mode, BE32 is modelled as
+             * little endian, with the appropriate address translations on
+             * non-word accesses. So sctlr.b only affects overall
+             * endianness in user mode
+             */
+            arm_sctlr_b(env) ||
+#endif
+                ((env->uncached_cpsr & CPSR_E) ? 1 : 0);
     }
 
     cur_el = arm_current_el(env);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 14/17] target-arm: implement BE32 mode in system emulation
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (12 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 13/17] arm: linux-user: don't set CPSR.E in BE32 mode Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 17:39   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 15/17] loader: add API to load elf header Peter Crosthwaite
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

From: Paolo Bonzini <pbonzini@redhat.com>

System emulation only has a little-endian target; BE32 mode
is implemented by adjusting the low bits of the address
for every byte and halfword load and store.  64-bit accesses
flip the low and high words.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[PC changes:
  * rebased against master (Jan 2016)
]
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 target-arm/cpu.h       |  5 ++-
 target-arm/translate.c | 86 +++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 96b1e99..5814019 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1925,9 +1925,8 @@ static inline bool bswap_code(bool sctlr_b)
 #endif
         sctlr_b;
 #else
-    /* We do not implement BE32 mode for system-mode emulation, but
-     * anyway it would always do little-endian accesses with
-     * TARGET_WORDS_BIGENDIAN = 0.
+    /* All code access in ARM is little endian, and there are no loaders
+     * doing swaps that need to be reversed
      */
     return 0;
 #endif
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 44c3ac9..2d80bb2 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -914,6 +914,12 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
     }
 }
 
+#ifdef CONFIG_USER_ONLY
+#define IS_USER_ONLY 1
+#else
+#define IS_USER_ONLY 0
+#endif
+
 /* Abstractions of "generate code to do a guest load/store for
  * AArch32", where a vaddr is always 32 bits (and is zero
  * extended if we're a 64 bit core) and  data is also
@@ -923,19 +929,35 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
  */
 #if TARGET_LONG_BITS == 32
 
-#define DO_GEN_LD(SUFF, OPC)                                             \
+#define DO_GEN_LD(SUFF, OPC, BE32_XOR)                                   \
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,      \
                                      TCGv_i32 addr, int index)           \
 {                                                                        \
     TCGMemOp opc = (OPC) | s->mo_endianness;                             \
+    /* Not needed for user-mode BE32, where we use MO_BE instead.  */    \
+    if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {                       \
+        TCGv addr_be = tcg_temp_new();                                   \
+        tcg_gen_xori_i32(addr_be, addr, BE32_XOR);                       \
+        tcg_gen_qemu_ld_i32(val, addr_be, index, opc);                   \
+        tcg_temp_free(addr_be);                                          \
+        return;                                                          \
+    }                                                                    \
     tcg_gen_qemu_ld_i32(val, addr, index, opc);                          \
 }
 
-#define DO_GEN_ST(SUFF, OPC)                                             \
+#define DO_GEN_ST(SUFF, OPC, BE32_XOR)                                   \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,      \
                                      TCGv_i32 addr, int index)           \
 {                                                                        \
     TCGMemOp opc = (OPC) | s->mo_endianness;                             \
+    /* Not needed for user-mode BE32, where we use MO_BE instead.  */    \
+    if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {                       \
+        TCGv addr_be = tcg_temp_new();                                   \
+        tcg_gen_xori_i32(addr_be, addr, BE32_XOR);                       \
+        tcg_gen_qemu_ld_i32(val, addr_be, index, opc);                   \
+        tcg_temp_free(addr_be);                                          \
+        return;                                                          \
+    }                                                                    \
     tcg_gen_qemu_st_i32(val, addr, index, opc);                          \
 }
 
@@ -944,35 +966,55 @@ static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
 {
     TCGMemOp opc = MO_Q | s->mo_endianness;
     tcg_gen_qemu_ld_i64(val, addr, index, opc);
+    /* Not needed for user-mode BE32, where we use MO_BE instead.  */
+    if (!IS_USER_ONLY && s->sctlr_b) {
+        tcg_gen_rotri_i64(val, val, 32);
+    }
 }
 
 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
                                  TCGv_i32 addr, int index)
 {
     TCGMemOp opc = MO_Q | s->mo_endianness;
+    /* Not needed for user-mode BE32, where we use MO_BE instead.  */
+    if (!IS_USER_ONLY && s->sctlr_b) {
+        TCGv_i64 tmp = tcg_temp_new_i64();
+        tcg_gen_rotri_i64(tmp, val, 32);
+        tcg_gen_qemu_st_i64(tmp, addr, index, opc);
+        tcg_temp_free_i64(tmp);
+        return;
+    }
     tcg_gen_qemu_st_i64(val, addr, index, opc);
 }
 
 #else
 
-#define DO_GEN_LD(SUFF, OPC)                                             \
+#define DO_GEN_LD(SUFF, OPC, BE32_XOR)                                   \
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,      \
                                      TCGv_i32 addr, int index)           \
 {                                                                        \
     TCGMemOp opc = (OPC) | s->mo_endianness;                             \
     TCGv addr64 = tcg_temp_new();                                        \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
+    /* Not needed for user-mode BE32, where we use MO_BE instead.  */    \
+    if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {                       \
+        tcg_gen_xori_i64(addr64, addr64, BE32_XOR);                      \
+    }                                                                    \
     tcg_gen_qemu_ld_i32(val, addr64, index, opc);                        \
     tcg_temp_free(addr64);                                               \
 }
 
-#define DO_GEN_ST(SUFF, OPC)                                             \
+#define DO_GEN_ST(SUFF, OPC, BE32_XOR)                                   \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,      \
                                      TCGv_i32 addr, int index)           \
 {                                                                        \
     TCGMemOp opc = (OPC) | s->mo_endianness;                             \
     TCGv addr64 = tcg_temp_new();                                        \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
+    /* Not needed for user-mode BE32, where we use MO_BE instead.  */    \
+    if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {                       \
+        tcg_gen_xori_i64(addr64, addr64, BE32_XOR);                      \
+    }                                                                    \
     tcg_gen_qemu_st_i32(val, addr64, index, opc);                        \
     tcg_temp_free(addr64);                                               \
 }
@@ -984,6 +1026,11 @@ static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
     tcg_gen_qemu_ld_i64(val, addr64, index, opc);
+
+    /* Not needed for user-mode BE32, where we use MO_BE instead.  */
+    if (!IS_USER_ONLY && s->sctlr_b) {
+        tcg_gen_rotri_i64(val, val, 32);
+    }
     tcg_temp_free(addr64);
 }
 
@@ -993,23 +1040,32 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
     TCGMemOp opc = MO_Q | s->mo_endianness;
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
-    tcg_gen_qemu_st_i64(val, addr64, index, opc);
+
+    /* Not needed for user-mode BE32, where we use MO_BE instead.  */
+    if (!IS_USER_ONLY && s->sctlr_b) {
+        TCGv tmp = tcg_temp_new();
+        tcg_gen_rotri_i64(tmp, val, 32);
+        tcg_gen_qemu_st_i64(tmp, addr64, index, opc);
+        tcg_temp_free(tmp);
+    } else {
+        tcg_gen_qemu_st_i64(val, addr64, index, opc);
+    }
     tcg_temp_free(addr64);
 }
 
 #endif
 
-DO_GEN_LD(8s, MO_SB)
-DO_GEN_LD(8u, MO_UB)
-DO_GEN_LD(16s, MO_SW)
-DO_GEN_LD(16u, MO_UW)
-DO_GEN_LD(32u, MO_UL)
+DO_GEN_LD(8s, MO_SB, 3)
+DO_GEN_LD(8u, MO_UB, 3)
+DO_GEN_LD(16s, MO_SW, 2)
+DO_GEN_LD(16u, MO_UW, 2)
+DO_GEN_LD(32u, MO_UL, 0)
 /* 'a' variants include an alignment check */
-DO_GEN_LD(16ua, MO_UW | MO_ALIGN)
-DO_GEN_LD(32ua, MO_UL | MO_ALIGN)
-DO_GEN_ST(8, MO_UB)
-DO_GEN_ST(16, MO_UW)
-DO_GEN_ST(32, MO_UL)
+DO_GEN_LD(16ua, MO_UW | MO_ALIGN, 2)
+DO_GEN_LD(32ua, MO_UL | MO_ALIGN, 0)
+DO_GEN_ST(8, MO_UB, 3)
+DO_GEN_ST(16, MO_UW, 2)
+DO_GEN_ST(32, MO_UL, 0)
 
 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
 {
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 15/17] loader: add API to load elf header
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (13 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 14/17] target-arm: implement BE32 mode in system emulation Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 17:50   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf Peter Crosthwaite
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

Add an API to load an elf header header from a file. Populates a
buffer with the header contents, as well as a boolean for whether the
elf is 64b or not. Both arguments are optional.

Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 hw/core/loader.c    | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/loader.h |  1 +
 2 files changed, 49 insertions(+)

diff --git a/hw/core/loader.c b/hw/core/loader.c
index 6b69852..28da8e2 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -331,6 +331,54 @@ const char *load_elf_strerror(int error)
     }
 }
 
+void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp)
+{
+    int fd;
+    uint8_t e_ident[EI_NIDENT];
+    size_t hdr_size, off = 0;
+    bool is64l;
+
+    fd = open(filename, O_RDONLY | O_BINARY);
+    if (fd < 0) {
+        error_setg_errno(errp, errno, "Fail to open file");
+        return;
+    }
+    if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident)) {
+        error_setg_errno(errp, errno, "Fail to read file");
+        goto fail;
+    }
+    if (e_ident[0] != ELFMAG0 ||
+        e_ident[1] != ELFMAG1 ||
+        e_ident[2] != ELFMAG2 ||
+        e_ident[3] != ELFMAG3) {
+        error_setg(errp, "Bad ELF magic");
+        goto fail;
+    }
+
+    is64l = e_ident[EI_CLASS] == ELFCLASS64;
+    hdr_size = is64l ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr);
+    if (is64) {
+        *is64 = is64l;
+    }
+
+    lseek(fd, 0, SEEK_SET);
+    while (hdr && off < hdr_size) {
+        size_t br = read(fd, hdr + off, hdr_size - off);
+        switch (br) {
+        case 0:
+            error_setg(errp, "File too short");
+            goto fail;
+        case -1:
+            error_setg_errno(errp, errno, "Failed to read file");
+            goto fail;
+        }
+        off += br;
+    }
+
+fail:
+    close(fd);
+}
+
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
              void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
diff --git a/include/hw/loader.h b/include/hw/loader.h
index f7b43ab..33067f8 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -36,6 +36,7 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
              void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
              uint64_t *highaddr, int big_endian, int elf_machine,
              int clear_lsb);
+void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
 int load_aout(const char *filename, hwaddr addr, int max_sz,
               int bswap_needed, hwaddr target_page_size);
 int load_uimage(const char *filename, hwaddr *ep,
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (14 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 15/17] loader: add API to load elf header Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 17:53   ` Peter Maydell
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 17/17] arm: boot: Support big-endian elfs Peter Crosthwaite
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

Some CPUs are of an opposite data-endianness to other components in the
system. Sometimes elfs have the data sections layed out with this CPU
data-endianess accounting for when loaded via the CPU, byte swaps
(relative to other system components) will occur.

The leading example, is ARM's BE32 mode, which is is basically LE with
address manipulation on half-word and byte accesses to access the
hw/byte reversed address. This means that word data is invariant
accross LE and BE32. This also means that instructions are still LE.
The expectation is that the elf will be loaded via the CPU in this
endianness scheme, which means the data in the elf is reversed at
compile time.

As QEMU loads via the system memory directly, rather than the CPU, we
need a mechanism to reverse elf data endianness to implement this
possibility.

Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 hw/alpha/dp264.c               |  4 ++--
 hw/arm/armv7m.c                |  2 +-
 hw/arm/boot.c                  |  2 +-
 hw/core/loader.c               |  9 ++++++---
 hw/cris/boot.c                 |  2 +-
 hw/i386/multiboot.c            |  3 ++-
 hw/lm32/lm32_boards.c          |  4 ++--
 hw/lm32/milkymist.c            |  2 +-
 hw/m68k/an5206.c               |  2 +-
 hw/m68k/dummy_m68k.c           |  2 +-
 hw/m68k/mcf5208.c              |  2 +-
 hw/microblaze/boot.c           |  4 ++--
 hw/mips/mips_fulong2e.c        |  2 +-
 hw/mips/mips_malta.c           |  2 +-
 hw/mips/mips_mipssim.c         |  2 +-
 hw/mips/mips_r4k.c             |  2 +-
 hw/moxie/moxiesim.c            |  3 ++-
 hw/openrisc/openrisc_sim.c     |  3 ++-
 hw/pci-host/prep.c             |  2 +-
 hw/ppc/e500.c                  |  2 +-
 hw/ppc/mac_newworld.c          |  5 +++--
 hw/ppc/mac_oldworld.c          |  5 +++--
 hw/ppc/ppc440_bamboo.c         |  3 ++-
 hw/ppc/spapr.c                 |  6 ++++--
 hw/ppc/virtex_ml507.c          |  3 ++-
 hw/s390x/ipl.c                 |  4 ++--
 hw/sparc/leon3.c               |  2 +-
 hw/sparc/sun4m.c               |  4 ++--
 hw/sparc64/sun4u.c             |  4 ++--
 hw/tricore/tricore_testboard.c |  2 +-
 hw/xtensa/sim.c                |  4 ++--
 hw/xtensa/xtfpga.c             |  2 +-
 include/hw/elf_ops.h           | 22 +++++++++++++++++++++-
 include/hw/loader.h            |  2 +-
 34 files changed, 78 insertions(+), 46 deletions(-)

diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index 27bdaa1..df071fa 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -109,7 +109,7 @@ static void clipper_init(MachineState *machine)
     }
     size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
                     NULL, &palcode_entry, &palcode_low, &palcode_high,
-                    0, EM_ALPHA, 0);
+                    0, EM_ALPHA, 0, 0);
     if (size < 0) {
         hw_error("could not load palcode '%s'\n", palcode_filename);
         exit(1);
@@ -129,7 +129,7 @@ static void clipper_init(MachineState *machine)
 
         size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
                         NULL, &kernel_entry, &kernel_low, &kernel_high,
-                        0, EM_ALPHA, 0);
+                        0, EM_ALPHA, 0, 0);
         if (size < 0) {
             hw_error("could not load kernel '%s'\n", kernel_filename);
             exit(1);
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index a80d2ad..d721e5b 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -210,7 +210,7 @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
 
     if (kernel_filename) {
         image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
-                              NULL, big_endian, EM_ARM, 1);
+                              NULL, big_endian, EM_ARM, 1, 0);
         if (image_size < 0) {
             image_size = load_image_targphys(kernel_filename, 0, mem_size);
             lowaddr = 0;
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 75f69bf..0de4269 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -700,7 +700,7 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
     /* Assume that raw images are linux kernels, and ELF images are not.  */
     kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
                            &elf_low_addr, &elf_high_addr, big_endian,
-                           elf_machine, 1);
+                           elf_machine, 1, 0);
     if (kernel_size > 0 && have_dtb(info)) {
         /* If there is still some room left at the base of RAM, try and put
          * the DTB there like we do for images loaded with -bios or -pflash.
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 28da8e2..bee6cf5 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -382,7 +382,8 @@ fail:
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
              void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
-             uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
+             uint64_t *highaddr, int big_endian, int elf_machine,
+             int clear_lsb, int data_swab)
 {
     int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
     uint8_t e_ident[EI_NIDENT];
@@ -421,10 +422,12 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
     lseek(fd, 0, SEEK_SET);
     if (e_ident[EI_CLASS] == ELFCLASS64) {
         ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
-                         pentry, lowaddr, highaddr, elf_machine, clear_lsb);
+                         pentry, lowaddr, highaddr, elf_machine, clear_lsb,
+                         data_swab);
     } else {
         ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
-                         pentry, lowaddr, highaddr, elf_machine, clear_lsb);
+                         pentry, lowaddr, highaddr, elf_machine, clear_lsb,
+                         data_swab);
     }
 
  fail:
diff --git a/hw/cris/boot.c b/hw/cris/boot.c
index 1cfa339..d08b307 100644
--- a/hw/cris/boot.c
+++ b/hw/cris/boot.c
@@ -72,7 +72,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
     /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
        devboard SDK.  */
     image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
-                          &entry, NULL, &high, 0, EM_CRIS, 0);
+                          &entry, NULL, &high, 0, EM_CRIS, 0, 0);
     li->entry = entry;
     if (image_size < 0) {
         /* Takes a kimage from the axis devboard SDK.  */
diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c
index 6774a19..b4435fa 100644
--- a/hw/i386/multiboot.c
+++ b/hw/i386/multiboot.c
@@ -195,7 +195,8 @@ int load_multiboot(FWCfgState *fw_cfg,
         }
 
         kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                               &elf_low, &elf_high, 0, I386_ELF_MACHINE, 0);
+                               &elf_low, &elf_high, 0, I386_ELF_MACHINE,
+                               0, 0);
         if (kernel_size < 0) {
             fprintf(stderr, "Error while loading elf kernel\n");
             exit(1);
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
index eb553a1..9b921c4 100644
--- a/hw/lm32/lm32_boards.c
+++ b/hw/lm32/lm32_boards.c
@@ -142,7 +142,7 @@ static void lm32_evr_init(MachineState *machine)
         int kernel_size;
 
         kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
-                               1, EM_LATTICEMICO32, 0);
+                               1, EM_LATTICEMICO32, 0, 0);
         reset_info->bootstrap_pc = entry;
 
         if (kernel_size < 0) {
@@ -244,7 +244,7 @@ static void lm32_uclinux_init(MachineState *machine)
         int kernel_size;
 
         kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
-                               1, EM_LATTICEMICO32, 0);
+                               1, EM_LATTICEMICO32, 0, 0);
         reset_info->bootstrap_pc = entry;
 
         if (kernel_size < 0) {
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 13976b3..fe50d7e 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -176,7 +176,7 @@ milkymist_init(MachineState *machine)
 
         /* Boots a kernel elf binary.  */
         kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
-                               1, EM_LATTICEMICO32, 0);
+                               1, EM_LATTICEMICO32, 0, 0);
         reset_info->bootstrap_pc = entry;
 
         if (kernel_size < 0) {
diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
index c1dea17..c869f12 100644
--- a/hw/m68k/an5206.c
+++ b/hw/m68k/an5206.c
@@ -70,7 +70,7 @@ static void an5206_init(MachineState *machine)
     }
 
     kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                           NULL, NULL, 1, EM_68K, 0);
+                           NULL, NULL, 1, EM_68K, 0, 0);
     entry = elf_entry;
     if (kernel_size < 0) {
         kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c
index 8b3b775..9482309 100644
--- a/hw/m68k/dummy_m68k.c
+++ b/hw/m68k/dummy_m68k.c
@@ -49,7 +49,7 @@ static void dummy_m68k_init(MachineState *machine)
     /* Load kernel.  */
     if (kernel_filename) {
         kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                               NULL, NULL, 1, EM_68K, 0);
+                               NULL, NULL, 1, EM_68K, 0, 0);
         entry = elf_entry;
         if (kernel_size < 0) {
             kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index ddeccc5..42cf0f3 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -275,7 +275,7 @@ static void mcf5208evb_init(MachineState *machine)
     }
 
     kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                           NULL, NULL, 1, EM_68K, 0);
+                           NULL, NULL, 1, EM_68K, 0, 0);
     entry = elf_entry;
     if (kernel_size < 0) {
         kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index d7eaa1f..d2cd85a 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -141,12 +141,12 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
         /* Boots a kernel elf binary.  */
         kernel_size = load_elf(kernel_filename, NULL, NULL,
                                &entry, &low, &high,
-                               big_endian, EM_MICROBLAZE, 0);
+                               big_endian, EM_MICROBLAZE, 0, 0);
         base32 = entry;
         if (base32 == 0xc0000000) {
             kernel_size = load_elf(kernel_filename, translate_kernel_address,
                                    NULL, &entry, NULL, NULL,
-                                   big_endian, EM_MICROBLAZE, 0);
+                                   big_endian, EM_MICROBLAZE, 0, 0);
         }
         /* Always boot into physical ram.  */
         boot_info.bootstrap_pc = (uint32_t)entry;
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index 5988a88..5b29db0 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -116,7 +116,7 @@ static int64_t load_kernel (CPUMIPSState *env)
 
     if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
                  (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
-                 (uint64_t *)&kernel_high, 0, EM_MIPS, 1) < 0) {
+                 (uint64_t *)&kernel_high, 0, EM_MIPS, 1, 0) < 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",
                 loaderparams.kernel_filename);
         exit(1);
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 91c36ba..25cf344 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -795,7 +795,7 @@ static int64_t load_kernel (void)
 
     if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
                  (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
-                 big_endian, EM_MIPS, 1) < 0) {
+                 big_endian, EM_MIPS, 1, 0) < 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",
                 loaderparams.kernel_filename);
         exit(1);
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c
index 23b35be..f08ceb7 100644
--- a/hw/mips/mips_mipssim.c
+++ b/hw/mips/mips_mipssim.c
@@ -69,7 +69,7 @@ static int64_t load_kernel(void)
     kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
                            NULL, (uint64_t *)&entry, NULL,
                            (uint64_t *)&kernel_high, big_endian,
-                           EM_MIPS, 1);
+                           EM_MIPS, 1, 0);
     if (kernel_size >= 0) {
         if ((entry & ~0x7fffffffULL) == 0x80000000)
             entry = (int32_t)entry;
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index af10da1..71a3646 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -87,7 +87,7 @@ static int64_t load_kernel(void)
     kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
                            NULL, (uint64_t *)&entry, NULL,
                            (uint64_t *)&kernel_high, big_endian,
-                           EM_MIPS, 1);
+                           EM_MIPS, 1, 0);
     if (kernel_size >= 0) {
         if ((entry & ~0x7fffffffULL) == 0x80000000)
             entry = (int32_t)entry;
diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c
index ada3d58..fa28dac 100644
--- a/hw/moxie/moxiesim.c
+++ b/hw/moxie/moxiesim.c
@@ -53,7 +53,8 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
     ram_addr_t initrd_offset;
 
     kernel_size = load_elf(loader_params->kernel_filename,  NULL, NULL,
-                           &entry, &kernel_low, &kernel_high, 1, EM_MOXIE, 0);
+                           &entry, &kernel_low, &kernel_high, 1, EM_MOXIE,
+                           0, 0);
 
     if (kernel_size <= 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index be6c9b5..a99be45 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -68,7 +68,8 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
 
     if (kernel_filename && !qtest_enabled()) {
         kernel_size = load_elf(kernel_filename, NULL, NULL,
-                               &elf_entry, NULL, NULL, 1, EM_OPENRISC, 1);
+                               &elf_entry, NULL, NULL, 1, EM_OPENRISC,
+                               1, 0);
         entry = elf_entry;
         if (kernel_size < 0) {
             kernel_size = load_uimage(kernel_filename,
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index da88cb3..da1c7da 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -312,7 +312,7 @@ static void raven_realize(PCIDevice *d, Error **errp)
         if (filename) {
             if (s->elf_machine != EM_NONE) {
                 bios_size = load_elf(filename, NULL, NULL, NULL,
-                                     NULL, NULL, 1, s->elf_machine, 0);
+                                     NULL, NULL, 1, s->elf_machine, 0, 0);
             }
             if (bios_size < 0) {
                 bios_size = get_image_size(filename);
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index b3418db..c73c699 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -1017,7 +1017,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 
     bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL,
-                         1, PPC_ELF_MACHINE, 0);
+                         1, PPC_ELF_MACHINE, 0, 0);
     if (bios_size < 0) {
         /*
          * Hrm. No ELF image? Try a uImage, maybe someone is giving us an
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 1b9a573..4cc0668 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -219,7 +219,7 @@ static void ppc_core99_init(MachineState *machine)
     /* Load OpenBIOS (ELF) */
     if (filename) {
         bios_size = load_elf(filename, NULL, NULL, NULL,
-                             NULL, NULL, 1, PPC_ELF_MACHINE, 0);
+                             NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
 
         g_free(filename);
     } else {
@@ -242,7 +242,8 @@ static void ppc_core99_init(MachineState *machine)
         kernel_base = KERNEL_LOAD_ADDR;
 
         kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
-                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
+                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
+                               0, 0);
         if (kernel_size < 0)
             kernel_size = load_aout(kernel_filename, kernel_base,
                                     ram_size - kernel_base, bswap_needed,
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 21eaf0e..1717cea 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -147,7 +147,7 @@ static void ppc_heathrow_init(MachineState *machine)
     /* Load OpenBIOS (ELF) */
     if (filename) {
         bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
-                             1, PPC_ELF_MACHINE, 0);
+                             1, PPC_ELF_MACHINE, 0, 0);
         g_free(filename);
     } else {
         bios_size = -1;
@@ -168,7 +168,8 @@ static void ppc_heathrow_init(MachineState *machine)
 #endif
         kernel_base = KERNEL_LOAD_ADDR;
         kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
-                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
+                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
+                               0, 0);
         if (kernel_size < 0)
             kernel_size = load_aout(kernel_filename, kernel_base,
                                     ram_size - kernel_base, bswap_needed,
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index b66c113..3fb1bac 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -256,7 +256,8 @@ static void bamboo_init(MachineState *machine)
                               NULL, NULL);
         if (success < 0) {
             success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
+                               &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE,
+                               0, 0);
             entry = elf_entry;
             loadaddr = elf_lowaddr;
         }
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 6bfb908..f6f0af3 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1934,11 +1934,13 @@ static void ppc_spapr_init(MachineState *machine)
         uint64_t lowaddr = 0;
 
         kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
-                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
+                               NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
+                               0, 0);
         if (kernel_size == ELF_LOAD_WRONG_ENDIAN) {
             kernel_size = load_elf(kernel_filename,
                                    translate_kernel_address, NULL,
-                                   NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE, 0);
+                                   NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE,
+                                   0, 0);
             kernel_le = kernel_size > 0;
         }
         if (kernel_size < 0) {
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index c2b5e44..12a6681 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -257,7 +257,8 @@ static void virtex_init(MachineState *machine)
 
         /* Boots a kernel elf binary.  */
         kernel_size = load_elf(kernel_filename, NULL, NULL,
-                               &entry, &low, &high, 1, PPC_ELF_MACHINE, 0);
+                               &entry, &low, &high, 1, PPC_ELF_MACHINE,
+                               0, 0);
         boot_info.bootstrap_pc = entry & 0x00ffffff;
 
         if (kernel_size < 0) {
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index b91fcc6..2446fa7 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -100,7 +100,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
 
         bios_size = load_elf(bios_filename, bios_translate_addr, &fwbase,
                              &ipl->bios_start_addr, NULL, NULL, 1,
-                             EM_S390, 0);
+                             EM_S390, 0, 0);
         if (bios_size > 0) {
             /* Adjust ELF start address to final location */
             ipl->bios_start_addr += fwbase;
@@ -123,7 +123,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
 
     if (ipl->kernel) {
         kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
-                               NULL, 1, EM_S390, 0);
+                               NULL, 1, EM_S390, 0, 0);
         if (kernel_size < 0) {
             kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
         }
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 22d1e7e..e10b2a5 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -193,7 +193,7 @@ static void leon3_generic_hw_init(MachineState *machine)
         uint64_t entry;
 
         kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
-                               1 /* big endian */, EM_SPARC, 0);
+                               1 /* big endian */, EM_SPARC, 0, 0);
         if (kernel_size < 0) {
             fprintf(stderr, "qemu: could not load kernel '%s'\n",
                     kernel_filename);
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 230dac9..0203bd8 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -300,7 +300,7 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
         bswap_needed = 0;
 #endif
         kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
-                               NULL, NULL, NULL, 1, EM_SPARC, 0);
+                               NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
         if (kernel_size < 0)
             kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
                                     RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
@@ -744,7 +744,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
     if (filename) {
         ret = load_elf(filename, translate_prom_address, &addr, NULL,
-                       NULL, NULL, 1, EM_SPARC, 0);
+                       NULL, NULL, 1, EM_SPARC, 0, 0);
         if (ret < 0 || ret > PROM_SIZE_MAX) {
             ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
         }
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index d6b929c..683605c 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -208,7 +208,7 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
         bswap_needed = 0;
 #endif
         kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
-                               kernel_addr, &kernel_top, 1, EM_SPARCV9, 0);
+                               kernel_addr, &kernel_top, 1, EM_SPARCV9, 0, 0);
         if (kernel_size < 0) {
             *kernel_addr = KERNEL_LOAD_ADDR;
             *kernel_entry = KERNEL_LOAD_ADDR;
@@ -671,7 +671,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
     if (filename) {
         ret = load_elf(filename, translate_prom_address, &addr,
-                       NULL, NULL, NULL, 1, EM_SPARCV9, 0);
+                       NULL, NULL, NULL, 1, EM_SPARCV9, 0, 0);
         if (ret < 0 || ret > PROM_SIZE_MAX) {
             ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
         }
diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c
index 4ff5e7b..a1ed338 100644
--- a/hw/tricore/tricore_testboard.c
+++ b/hw/tricore/tricore_testboard.c
@@ -44,7 +44,7 @@ static void tricore_load_kernel(CPUTriCoreState *env)
     kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
                            NULL, (uint64_t *)&entry, NULL,
                            NULL, 0,
-                           EM_TRICORE, 1);
+                           EM_TRICORE, 1, 0);
     if (kernel_size <= 0) {
         error_report("qemu: no kernel file '%s'",
                 tricoretb_binfo.kernel_filename);
diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c
index 6266b8d..6008eee 100644
--- a/hw/xtensa/sim.c
+++ b/hw/xtensa/sim.c
@@ -93,10 +93,10 @@ static void xtensa_sim_init(MachineState *machine)
         uint64_t elf_lowaddr;
 #ifdef TARGET_WORDS_BIGENDIAN
         int success = load_elf(kernel_filename, translate_phys_addr, cpu,
-                &elf_entry, &elf_lowaddr, NULL, 1, EM_XTENSA, 0);
+                &elf_entry, &elf_lowaddr, NULL, 1, EM_XTENSA, 0, 0);
 #else
         int success = load_elf(kernel_filename, translate_phys_addr, cpu,
-                &elf_entry, &elf_lowaddr, NULL, 0, EM_XTENSA, 0);
+                &elf_entry, &elf_lowaddr, NULL, 0, EM_XTENSA, 0, 0);
 #endif
         if (success > 0) {
             env->pc = elf_entry;
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index c1bc5ae..0bd0555 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -354,7 +354,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
         uint64_t elf_entry;
         uint64_t elf_lowaddr;
         int success = load_elf(kernel_filename, translate_phys_addr, cpu,
-                &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0);
+                &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0, 0);
         if (success > 0) {
             entry_point = elf_entry;
         } else {
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index 0010c44..f510e7e 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -263,7 +263,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
                               void *translate_opaque,
                               int must_swab, uint64_t *pentry,
                               uint64_t *lowaddr, uint64_t *highaddr,
-                              int elf_machine, int clear_lsb)
+                              int elf_machine, int clear_lsb, int data_swab)
 {
     struct elfhdr ehdr;
     struct elf_phdr *phdr = NULL, *ph;
@@ -366,6 +366,26 @@ static int glue(load_elf, SZ)(const char *name, int fd,
                 addr = ph->p_paddr;
             }
 
+            if (data_swab) {
+                int j;
+                for (j = 0; j < file_size; j += (1 << data_swab)) {
+                    uint8_t *dp = data + j;
+                    switch (data_swab) {
+                    case (1):
+                        *(uint16_t *)dp = bswap16(*(uint16_t *)dp);
+                        break;
+                    case (2):
+                        *(uint32_t *)dp = bswap32(*(uint32_t *)dp);
+                        break;
+                    case (3):
+                        *(uint64_t *)dp = bswap64(*(uint64_t *)dp);
+                        break;
+                    default:
+                        g_assert_not_reached();
+                    }
+                }
+            }
+
             /* the entry pointer in the ELF header is a virtual
              * address, if the text segments paddr and vaddr differ
              * we need to adjust the entry */
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 33067f8..e542575 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -35,7 +35,7 @@ const char *load_elf_strerror(int error);
 int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
              void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
              uint64_t *highaddr, int big_endian, int elf_machine,
-             int clear_lsb);
+             int clear_lsb, int data_swab);
 void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
 int load_aout(const char *filename, hwaddr addr, int max_sz,
               int bswap_needed, hwaddr target_page_size);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v1 17/17] arm: boot: Support big-endian elfs
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (15 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf Peter Crosthwaite
@ 2016-01-18  7:12 ` Peter Crosthwaite
  2016-01-19 18:06   ` Peter Maydell
  2016-01-19 18:06 ` [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Maydell
  2016-03-01  5:27 ` Stefan Weil
  18 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-01-18  7:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Peter Crosthwaite, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

Support ARM big-endian ELF files in system-mode emulation. When loading
an elf, determine the endianness mode expected by the elf, and set the
relevant CPU state accordingly.

With this, big-endian modes are now fully supported via system-mode LE,
so there is no need to restrict the elf loading to the TARGET
endianness so the ifdeffery on TARGET_WORDS_BIGENDIAN goes away.

Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---

 hw/arm/boot.c        | 96 ++++++++++++++++++++++++++++++++++++++++++----------
 include/hw/arm/arm.h |  9 +++++
 2 files changed, 88 insertions(+), 17 deletions(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 0de4269..053c9e8 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -465,9 +465,34 @@ static void do_cpu_reset(void *opaque)
     cpu_reset(cs);
     if (info) {
         if (!info->is_linux) {
+            int i;
             /* Jump to the entry point.  */
             uint64_t entry = info->entry;
 
+            switch (info->endianness) {
+            case ARM_ENDIANNESS_LE:
+                env->cp15.sctlr_el[1] &= ~SCTLR_E0E;
+                for (i = 1; i < 4; ++i) {
+                    env->cp15.sctlr_el[i] &= ~SCTLR_EE;
+                }
+                env->uncached_cpsr &= ~CPSR_E;
+                break;
+            case ARM_ENDIANNESS_BE8:
+                env->cp15.sctlr_el[1] |= SCTLR_E0E;
+                for (i = 1; i < 4; ++i) {
+                    env->cp15.sctlr_el[i] |= SCTLR_EE;
+                }
+                env->uncached_cpsr |= CPSR_E;
+                break;
+            case ARM_ENDIANNESS_BE32:
+                env->cp15.sctlr_el[1] |= SCTLR_B;
+                break;
+            case ARM_ENDIANNESS_UNKNOWN:
+                break; /* Board's decision */
+            default:
+                g_assert_not_reached();
+            }
+
             if (!env->aarch64) {
                 env->thumb = info->entry & 1;
                 entry &= 0xfffffffe;
@@ -589,16 +614,23 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
     int kernel_size;
     int initrd_size;
     int is_linux = 0;
+
     uint64_t elf_entry, elf_low_addr, elf_high_addr;
     int elf_machine;
+    bool elf_is64;
+    union {
+        Elf32_Ehdr h32;
+        Elf64_Ehdr h64;
+    } elf_header;
+
     hwaddr entry, kernel_load_offset;
-    int big_endian;
     static const ARMInsnFixup *primary_loader;
     ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
                                          notifier, notifier);
     ARMCPU *cpu = n->cpu;
     struct arm_boot_info *info =
         container_of(n, struct arm_boot_info, load_kernel_notifier);
+    Error *err = NULL;
 
     /* The board code is not supposed to set secure_board_setup unless
      * running its code in secure mode is actually possible, and KVM
@@ -678,12 +710,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
     if (info->nb_cpus == 0)
         info->nb_cpus = 1;
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-
     /* We want to put the initrd far enough into RAM that when the
      * kernel is uncompressed it will not clobber the initrd. However
      * on boards without much RAM we must ensure that we still leave
@@ -698,16 +724,52 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
         MIN(info->ram_size / 2, 128 * 1024 * 1024);
 
     /* Assume that raw images are linux kernels, and ELF images are not.  */
-    kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
-                           &elf_low_addr, &elf_high_addr, big_endian,
-                           elf_machine, 1, 0);
-    if (kernel_size > 0 && have_dtb(info)) {
-        /* If there is still some room left at the base of RAM, try and put
-         * the DTB there like we do for images loaded with -bios or -pflash.
-         */
-        if (elf_low_addr > info->loader_start
-            || elf_high_addr < info->loader_start) {
-            /* Pass elf_low_addr as address limit to load_dtb if it may be
+
+    load_elf_hdr(info->kernel_filename, &elf_header, &elf_is64, &err);
+
+    if (!err) {
+        int data_swab = 0;
+        bool big_endian;
+
+        if (elf_is64) {
+            big_endian = elf_header.h64.e_ident[EI_DATA] == ELFDATA2MSB;
+            info->endianness = big_endian ? ARM_ENDIANNESS_BE8
+                                          : ARM_ENDIANNESS_LE;
+        } else {
+            big_endian = elf_header.h32.e_ident[EI_DATA] == ELFDATA2MSB;
+            if (big_endian) {
+                if (bswap32(elf_header.h32.e_flags) & EF_ARM_BE8) {
+                    info->endianness = ARM_ENDIANNESS_BE8;
+                } else {
+                    info->endianness = ARM_ENDIANNESS_BE32;
+                    /* In BE32, the CPU has a different view of the per-byte
+                     * address map than the rest of the system. BE32 elfs are
+                     * organised such that they can be programmed through the
+                     * CPUs per-word byte-reversed view of the world. QEMU
+                     * however loads elfs independently of the CPU. So tell
+                     * the elf loader to byte reverse the data for us.
+                     */
+                    data_swab = 2;
+                }
+            } else {
+                info->endianness = ARM_ENDIANNESS_LE;
+            }
+        }
+
+        kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
+                               &elf_low_addr, &elf_high_addr, big_endian,
+                               elf_machine, 1, data_swab);
+        if (kernel_size <= 0) {
+            exit(1);
+        }
+
+        if (have_dtb(info) && (elf_low_addr > info->loader_start ||
+                               elf_high_addr < info->loader_start)) {
+            /* If there is still some room left at the base of RAM, try and
+             * put the DTB there like we do for images loaded with -bios or
+             * -pflash.
+             *
+             * Pass elf_low_addr as address limit to load_dtb if it may be
              * pointing into RAM, otherwise pass '0' (no limit)
              */
             if (elf_low_addr < info->loader_start) {
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index c26b0e3..75d77c9 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -16,6 +16,13 @@
 #include "qemu/notify.h"
 #include "cpu.h"
 
+typedef enum {
+    ARM_ENDIANNESS_UNKNOWN = 0,
+    ARM_ENDIANNESS_LE,
+    ARM_ENDIANNESS_BE8,
+    ARM_ENDIANNESS_BE32,
+} arm_endianness;
+
 /* armv7m.c */
 DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
                       const char *kernel_filename, const char *cpu_model);
@@ -103,6 +110,8 @@ struct arm_boot_info {
      * changing to non-secure state if implementing a non-secure boot
      */
     bool secure_board_setup;
+
+    arm_endianness endianness;
 };
 
 /**
-- 
1.9.1

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

* Re: [Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header Peter Crosthwaite
@ 2016-01-18 21:52   ` Alistair Francis
  2016-01-19 16:11   ` Peter Maydell
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2016-01-18 21:52 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Maydell, Peter Crosthwaite,
	qemu-devel@nongnu.org Developers, Alistair Francis, sridhar_kulk,
	qemu-arm, Paolo Bonzini, piotr.krol

On Sun, Jan 17, 2016 at 11:12 PM, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>
> There is a CPU data endianness test that is used to drive the
> virtio_big_endian test.
>
> Move this up to the header so it can be more generally used for endian
> tests. The KVM specific cpu_syncronize_state call is left behind in the
> virtio specific function.
>
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>

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

Also, I'm not too sure what the appropriate action is here, but this
is still signed off by your Xilinx address.

Thanks,

Alistair

> ---
>
>  target-arm/cpu.c | 19 +++----------------
>  target-arm/cpu.h | 19 +++++++++++++++++++
>  2 files changed, 22 insertions(+), 16 deletions(-)
>
> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> index 35a1f12..d3b73bf 100644
> --- a/target-arm/cpu.c
> +++ b/target-arm/cpu.c
> @@ -368,26 +368,13 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
>  #endif
>  }
>
> -static bool arm_cpu_is_big_endian(CPUState *cs)
> +static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
>  {
>      ARMCPU *cpu = ARM_CPU(cs);
>      CPUARMState *env = &cpu->env;
> -    int cur_el;
>
>      cpu_synchronize_state(cs);
> -
> -    /* In 32bit guest endianness is determined by looking at CPSR's E bit */
> -    if (!is_a64(env)) {
> -        return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
> -    }
> -
> -    cur_el = arm_current_el(env);
> -
> -    if (cur_el == 0) {
> -        return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
> -    }
> -
> -    return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
> +    return arm_cpu_is_big_endian(env);
>  }
>
>  #endif
> @@ -1420,7 +1407,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>      cc->do_unaligned_access = arm_cpu_do_unaligned_access;
>      cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
>      cc->vmsd = &vmstate_arm_cpu;
> -    cc->virtio_is_big_endian = arm_cpu_is_big_endian;
> +    cc->virtio_is_big_endian = arm_cpu_virtio_is_big_endian;
>  #endif
>      cc->gdb_num_core_regs = 26;
>      cc->gdb_core_xml_file = "arm-core.xml";
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index f83070a..54675c7 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1795,6 +1795,25 @@ static inline bool arm_singlestep_active(CPUARMState *env)
>          && arm_generate_debug_exceptions(env);
>  }
>
> +/* Return true if the processor is in big-endian mode. */
> +static bool arm_cpu_is_big_endian(CPUARMState *env)
> +{
> +    int cur_el;
> +
> +    /* In 32bit endianness is determined by looking at CPSR's E bit */
> +    if (!is_a64(env)) {
> +        return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
> +    }
> +
> +    cur_el = arm_current_el(env);
> +
> +    if (cur_el == 0) {
> +        return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
> +    }
> +
> +    return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
> +}
> +
>  #include "exec/cpu-all.h"
>
>  /* Bit usage in the TB flags field: bit 31 indicates whether we are
> --
> 1.9.1
>
>

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

* Re: [Qemu-devel] [PATCH v1 04/17] target-arm: implement SCTLR.EE
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 04/17] target-arm: implement SCTLR.EE Peter Crosthwaite
@ 2016-01-19 15:58   ` Peter Maydell
  2016-02-27 21:56     ` Peter Crosthwaite
  0 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 15:58 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>
> Implement SCTLR.EE bit which controls data endianess for exceptions
> and page table translations. SCTLR.EE is mirrored to the CPSR.E bit
> on exception entry.
>
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
>
>  target-arm/helper.c | 42 ++++++++++++++++++++++++++++++++----------
>  1 file changed, 32 insertions(+), 10 deletions(-)
>
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 59d5a41..afac1b2 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -5889,7 +5889,10 @@ void arm_cpu_do_interrupt(CPUState *cs)
>      /* Clear IT bits.  */
>      env->condexec_bits = 0;
>      /* Switch to the new mode, and to the correct instruction set.  */
> -    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
> +    env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_M)) | new_mode;

Why change this line?

> +    /* Set new mode endianess */

"endianness"

> +    env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_E)) |
> +        (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE ? CPSR_E : 0);

This is a bit confusing. I think just splitting it into
multiple statements would help:
   env->uncached_cpsr &= ~CPSR_E;
   if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
       env->uncached_cpsr |= CPSR_E;
   }

>      env->daif |= mask;
>      /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
>       * and we should just guard the thumb mode on V4 */
> @@ -5958,6 +5961,12 @@ static inline bool regime_translation_disabled(CPUARMState *env,
>      return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
>  }
>
> +static inline bool regime_translation_big_endian(CPUARMState *env,
> +                                                 ARMMMUIdx mmu_idx)
> +{
> +    return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
> +}
> +
>  /* Return the TCR controlling this translation regime */
>  static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
>  {
> @@ -6263,7 +6272,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
>   */
>  static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
>                              ARMMMUIdx mmu_idx, uint32_t *fsr,
> -                            ARMMMUFaultInfo *fi)
> +                            ARMMMUFaultInfo *fi, bool be)
>  {
>      ARMCPU *cpu = ARM_CPU(cs);
>      CPUARMState *env = &cpu->env;
> @@ -6274,12 +6283,16 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
>      if (fi->s1ptw) {
>          return 0;
>      }
> -    return address_space_ldl(cs->as, addr, attrs, NULL);
> +    if (be) {
> +        return address_space_ldl_be(cs->as, addr, attrs, NULL);
> +    } else {
> +        return address_space_ldl_le(cs->as, addr, attrs, NULL);
> +    }
>  }

Why not just call regime_translation_big_endian() inside arm_ldl_ptw()
and arm_ldq_ptw(), rather than having every call site making the call
and passing in the result?

PS: this patch will conflict with the multi-ases series but only
fairly trivially.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 05/17] target-arm: pass DisasContext to gen_aa32_ld*/st*
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 05/17] target-arm: pass DisasContext to gen_aa32_ld*/st* Peter Crosthwaite
@ 2016-01-19 16:08   ` Peter Maydell
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 16:08 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Paolo Bonzini <pbonzini@redhat.com>
>
> We'll need the DisasContext in the next patch to retrieve the
> desired endianness, so pass it as a whole to gen_aa32_ld*/st*.
>
> Unfortunately we cannot let those functions call get_mem_index,
> because of user-mode load/store instructions.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> [ PC changes:
>  * Fix long lines
> ]
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 06/17] target-arm: introduce disas flag for endianness
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 06/17] target-arm: introduce disas flag for endianness Peter Crosthwaite
@ 2016-01-19 16:08   ` Peter Maydell
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 16:08 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Paolo Bonzini <pbonzini@redhat.com>
>
> Introduce a disas flag for setting the CPU data endianness. This allows
> control of the endianness from the CPU state rather than hard-coding it
> to TARGET_WORDS_BIGENDIAN.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> [ PC changes:
>   * Split off as new patch from original:
>         "target-arm: introduce tbflag for CPSR.E"
>   * Wrote commit message from scratch
> ]
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 07/17] target-arm: a64: Add endianness support
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 07/17] target-arm: a64: Add endianness support Peter Crosthwaite
@ 2016-01-19 16:09   ` Peter Maydell
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 16:09 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>
> Set the dc->mo_endianness flag for AA64 and use it in all ldst ops.
>
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header Peter Crosthwaite
  2016-01-18 21:52   ` Alistair Francis
@ 2016-01-19 16:11   ` Peter Maydell
  2016-02-27 22:02     ` Peter Crosthwaite
  1 sibling, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 16:11 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>
> There is a CPU data endianness test that is used to drive the
> virtio_big_endian test.
>
> Move this up to the header so it can be more generally used for endian
> tests. The KVM specific cpu_syncronize_state call is left behind in the
> virtio specific function.
>
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
>
>  target-arm/cpu.c | 19 +++----------------
>  target-arm/cpu.h | 19 +++++++++++++++++++
>  2 files changed, 22 insertions(+), 16 deletions(-)
>
> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> index 35a1f12..d3b73bf 100644
> --- a/target-arm/cpu.c
> +++ b/target-arm/cpu.c
> @@ -368,26 +368,13 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
>  #endif
>  }
>
> -static bool arm_cpu_is_big_endian(CPUState *cs)
> +static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
>  {
>      ARMCPU *cpu = ARM_CPU(cs);
>      CPUARMState *env = &cpu->env;
> -    int cur_el;
>
>      cpu_synchronize_state(cs);
> -
> -    /* In 32bit guest endianness is determined by looking at CPSR's E bit */
> -    if (!is_a64(env)) {
> -        return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
> -    }
> -
> -    cur_el = arm_current_el(env);
> -
> -    if (cur_el == 0) {
> -        return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
> -    }
> -
> -    return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
> +    return arm_cpu_is_big_endian(env);
>  }
>
>  #endif
> @@ -1420,7 +1407,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>      cc->do_unaligned_access = arm_cpu_do_unaligned_access;
>      cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
>      cc->vmsd = &vmstate_arm_cpu;
> -    cc->virtio_is_big_endian = arm_cpu_is_big_endian;
> +    cc->virtio_is_big_endian = arm_cpu_virtio_is_big_endian;
>  #endif
>      cc->gdb_num_core_regs = 26;
>      cc->gdb_core_xml_file = "arm-core.xml";
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index f83070a..54675c7 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1795,6 +1795,25 @@ static inline bool arm_singlestep_active(CPUARMState *env)
>          && arm_generate_debug_exceptions(env);
>  }
>
> +/* Return true if the processor is in big-endian mode. */
> +static bool arm_cpu_is_big_endian(CPUARMState *env)
> +{

No problems code-wise, but can we call the function
arm_cpu_data_is_big_endian() or something? This is returning the
endianness to use for data accesses; there isn't an overall
"big-endian mode" that affects everything except for the
obsolete BE32.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 09/17] target-arm: introduce tbflag for endianness
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 09/17] target-arm: introduce tbflag for endianness Peter Crosthwaite
@ 2016-01-19 16:15   ` Peter Maydell
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 16:15 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>
> Introduce a tbflags for endianness, set based upon the CPUs current
> endianness. This in turn propagates through to the disas endianness
> flag.
>
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
>
>  target-arm/cpu.h           | 7 +++++++
>  target-arm/translate-a64.c | 2 +-
>  target-arm/translate.c     | 2 +-
>  3 files changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 54675c7..74048d1 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1857,6 +1857,8 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
>   */
>  #define ARM_TBFLAG_NS_SHIFT         19
>  #define ARM_TBFLAG_NS_MASK          (1 << ARM_TBFLAG_NS_SHIFT)
> +#define ARM_TBFLAG_MOE_SHIFT        20
> +#define ARM_TBFLAG_MOE_MASK         (1 << ARM_TBFLAG_MOE_SHIFT)

Can we call the flag bit something that makes clear that it's the
data endianness (and that the sense is 'bit set for BE data'),
please? (We probably don't need MO in the name.)

>  /* Bit usage when in AArch64 state: currently we have no A64 specific bits */
>
> @@ -1887,6 +1889,8 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
>      (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
>  #define ARM_TBFLAG_NS(F) \
>      (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
> +#define ARM_TBFLAG_MOE(F) \
> +    (((F) & ARM_TBFLAG_MOE_MASK) >> ARM_TBFLAG_MOE_SHIFT)
>
>  /* Return the exception level to which FP-disabled exceptions should
>   * be taken, or 0 if FP is enabled.
> @@ -2018,6 +2022,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
>              }
>          }
>      }
> +    if (arm_cpu_is_big_endian(env)) {
> +        *flags |= ARM_TBFLAG_MOE_MASK;
> +    }

Doesn't this break BE32 linux-user? That wanted MO_TE and got it before this
patch, and now it will end up with MO_LE because arm_cpu_is_big_endian()
is only looking at BE8 related CPU status flags.

>      *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
>
>      *cs_base = 0;
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> index 59026b6..db68662 100644
> --- a/target-arm/translate-a64.c
> +++ b/target-arm/translate-a64.c
> @@ -11044,7 +11044,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
>                                 !arm_el_is_aa64(env, 3);
>      dc->thumb = 0;
>      dc->bswap_code = 0;
> -    dc->mo_endianness = MO_TE;
> +    dc->mo_endianness = ARM_TBFLAG_MOE(tb->flags) ? MO_BE : MO_LE;
>      dc->condexec_mask = 0;
>      dc->condexec_cond = 0;
>      dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index e1679d3..cb925ef 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -11274,7 +11274,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
>                                 !arm_el_is_aa64(env, 3);
>      dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
>      dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
> -    dc->mo_endianness = MO_TE;
> +    dc->mo_endianness = ARM_TBFLAG_MOE(tb->flags) ? MO_BE : MO_LE;
>      dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
>      dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
>      dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 02/17] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 02/17] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode Peter Crosthwaite
@ 2016-01-19 16:22   ` Peter Maydell
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 16:22 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>
> If doing big-endian linux-user mode, set both the CPSR.E and SCTLR.E0E
> bits. This sets big-endian mode for data accesses in AA32 and AA64
> resp.
>
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
>
>  linux-user/main.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index ee12035..4f8ea9c 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -4454,6 +4454,10 @@ int main(int argc, char **argv, char **envp)
>          for(i = 0; i < 16; i++) {
>              env->regs[i] = regs->uregs[i];
>          }
> +#ifdef TARGET_WORDS_BIGENDIAN
> +        env->uncached_cpsr |= CPSR_E;
> +        env->cp15.sctlr_el[1] |= SCTLR_E0E;
> +#endif

This looks a bit weird. Setting CPSR_E or SCTLR_E0E doesn't
make sense for BE32, and for BE8 we want to do it inside the
runtime-conditional below, I would have thought.

The commit message implies that this will work for AArch64, but
this won't have any effect for A64 binaries because it's inside
an ifndef(TARGET_AARCH64) block.

>          /* Enable BE8.  */
>          if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
>              && (info->elf_flags & EF_ARM_BE8)) {

Not sure how an AArch64 BE ELF file identifies itself, but I guess
if we're supporting it we want a similar condition for it.
Happy to leave the 64-bit support until we've got the 32-bit
stuff working though.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 03/17] linux-user: arm: handle CPSR.E correctly in strex emulation
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 03/17] linux-user: arm: handle CPSR.E correctly in strex emulation Peter Crosthwaite
@ 2016-01-19 16:24   ` Peter Maydell
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 16:24 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Paolo Bonzini <pbonzini@redhat.com>
>
> Now that CPSR.E is set correctly, prepare for when setend will be able
> to change it; bswap data in and out of strex manually by comparing
> SCTLR.B, CPSR.E and TARGET_WORDS_BIGENDIAN (we do not have the luxury
> of using TCGMemOps).
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> [ PC changes:
>   * Remove BE32 support
> ]
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---

I reviewed this with the BE32 changes in it, but this version is
missing them. I don't really want to go through thinking about
whether all the cases work again only with the BE32 cases
behaving different, when I did that the first time round
and will presumably have to do it again later when the BE32
support gets added back in again :-(

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 10/17] target-arm: implement setend
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 10/17] target-arm: implement setend Peter Crosthwaite
@ 2016-01-19 16:29   ` Peter Maydell
  2016-02-27 22:14     ` Peter Crosthwaite
  0 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 16:29 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Paolo Bonzini <pbonzini@redhat.com>
>
> Since this is not a high-performance path, just use a helper to
> flip the E bit and force a lookup in the hash table since the
> flags have changed.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---
>
>  target-arm/helper.h    |  1 +
>  target-arm/op_helper.c |  5 +++++
>  target-arm/translate.c | 16 ++++++++--------
>  3 files changed, 14 insertions(+), 8 deletions(-)
>
> diff --git a/target-arm/helper.h b/target-arm/helper.h
> index c2a85c7..2315a9c 100644
> --- a/target-arm/helper.h
> +++ b/target-arm/helper.h
> @@ -48,6 +48,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
>                     i32, i32, i32, i32)
>  DEF_HELPER_2(exception_internal, void, env, i32)
>  DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
> +DEF_HELPER_1(setend, void, env)
>  DEF_HELPER_1(wfi, void, env)
>  DEF_HELPER_1(wfe, void, env)
>  DEF_HELPER_1(yield, void, env)
> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
> index e42d287..2a4bc67 100644
> --- a/target-arm/op_helper.c
> +++ b/target-arm/op_helper.c
> @@ -295,6 +295,11 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
>      return res;
>  }
>
> +void HELPER(setend)(CPUARMState *env)
> +{
> +    env->uncached_cpsr ^= CPSR_E;
> +}
> +
>  /* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
>   * The function returns the target EL (1-3) if the instruction is to be trapped;
>   * otherwise it returns 0 indicating it is not trapped.
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index cb925ef..192a5d6 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -7726,10 +7726,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
>          if ((insn & 0x0ffffdff) == 0x01010000) {
>              ARCH(6);
>              /* setend */
> -            if (((insn >> 9) & 1) != s->bswap_code) {
> -                /* Dynamic endianness switching not implemented. */
> -                qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
> -                goto illegal_op;
> +            if (((insn >> 9) & 1) != !!(s->mo_endianness == MO_BE)) {
> +                gen_helper_setend(cpu_env);
> +                gen_set_pc_im(s, s->pc);
> +                s->is_jmp = DISAS_JUMP;

Rather than manually calling set_pc_im and using DISAS_JUMP, better
to use DISAS_UPDATE, which will do the gen_set_pc_im() call for you.

(Ditto in the other hunk.)

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 12/17] target-arm: implement SCTLR.B, drop bswap_code
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 12/17] target-arm: implement SCTLR.B, drop bswap_code Peter Crosthwaite
@ 2016-01-19 17:21   ` Peter Maydell
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 17:21 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Paolo Bonzini <pbonzini@redhat.com>
>
> bswap_code is a CPU property of sorts ("is the iside endianness the
> opposite way round to TARGET_WORDS_BIGENDIAN?") but it is not the
> actual CPU state involved here which is SCTLR.B (set for BE32
> binaries, clear for BE8).
>
> Replace bswap_code with SCTLR.B, and pass that to arm_ld*_code.
> The next patches will make data fetches honor both SCTLR.B and
> CPSR.E appropriately.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> [PC changes:
>  * rebased on master (Jan 2016)
>  * Dropped comment about CPSR.E being unimplemented
>  * s/TARGET_USER_ONLY/CONFIG_USER_ONLY
>  * Use bswap_code() for disas_set_info() instead of raw sctlr_b
> ]
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---
>
>  linux-user/main.c          | 13 ++++++++-----
>  target-arm/arm_ldst.h      |  8 ++++----
>  target-arm/cpu.c           |  2 +-
>  target-arm/cpu.h           | 47 ++++++++++++++++++++++++++++++++++++++--------
>  target-arm/helper.c        |  8 ++++----
>  target-arm/translate-a64.c |  6 +++---
>  target-arm/translate.c     | 12 ++++++------
>  target-arm/translate.h     |  2 +-
>  8 files changed, 66 insertions(+), 32 deletions(-)
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 2157774..d481458 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -441,7 +441,7 @@ void cpu_loop(CPUX86State *env)
>
>  #define get_user_code_u32(x, gaddr, env)                \
>      ({ abi_long __r = get_user_u32((x), (gaddr));       \
> -        if (!__r && (env)->bswap_code) {                \
> +        if (!__r && bswap_code(arm_sctlr_b(env))) {     \
>              (x) = bswap32(x);                           \
>          }                                               \
>          __r;                                            \
> @@ -449,7 +449,7 @@ void cpu_loop(CPUX86State *env)
>
>  #define get_user_code_u16(x, gaddr, env)                \
>      ({ abi_long __r = get_user_u16((x), (gaddr));       \
> -        if (!__r && (env)->bswap_code) {                \
> +        if (!__r && bswap_code(arm_sctlr_b(env))) {     \
>              (x) = bswap16(x);                           \
>          }                                               \
>          __r;                                            \
> @@ -4489,14 +4489,17 @@ int main(int argc, char **argv, char **envp)
>              env->regs[i] = regs->uregs[i];
>          }
>  #ifdef TARGET_WORDS_BIGENDIAN
> -        env->uncached_cpsr |= CPSR_E;
>          env->cp15.sctlr_el[1] |= SCTLR_E0E;
> -#endif
>          /* Enable BE8.  */
>          if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
>              && (info->elf_flags & EF_ARM_BE8)) {
> -            env->bswap_code = 1;
> +            env->uncached_cpsr |= CPSR_E;

...ah, this is fixing the problem I noted in the earlier patch.

> +        } else {
> +            env->cp15.sctlr_el[1] |= SCTLR_B;
> +            /* We model BE32 as regular BE, so set CPSR_E */
> +            env->uncached_cpsr |= CPSR_E;

...but we still set CPSR_E for BE32, which is wrong.

>          }
> +#endif
>      }
>  #elif defined(TARGET_UNICORE32)
>      {

The rest of this patch is all OK.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 13/17] arm: linux-user: don't set CPSR.E in BE32 mode
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 13/17] arm: linux-user: don't set CPSR.E in BE32 mode Peter Crosthwaite
@ 2016-01-19 17:26   ` Peter Maydell
  2016-01-19 17:35     ` Peter Maydell
  0 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 17:26 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> Don't set CPSR.E for BE32 linux-user mode. As linux-user mode models
> BE32, using normal BE (and system mode will not), a special case is
> needed for user-mode where if sctlr.b is set, the CPU identifies as BE.
>
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---
>
>  linux-user/main.c |  2 --
>  target-arm/cpu.h  | 12 +++++++++++-
>  2 files changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index d481458..60375fb 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -4496,8 +4496,6 @@ int main(int argc, char **argv, char **envp)
>              env->uncached_cpsr |= CPSR_E;
>          } else {
>              env->cp15.sctlr_el[1] |= SCTLR_B;
> -            /* We model BE32 as regular BE, so set CPSR_E */
> -            env->uncached_cpsr |= CPSR_E;

...this is undoing what we just did in the previous patch and
which I reviewed as being the wrong thing there...

>          }
>  #endif
>      }
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 3edd56b..96b1e99 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1812,7 +1812,17 @@ static bool arm_cpu_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 user mode, BE32 data accesses are just modelled as
> +             * regular BE access. In system mode, BE32 is modelled as
> +             * little endian, with the appropriate address translations on
> +             * non-word accesses. So sctlr.b only affects overall
> +             * endianness in user mode
> +             */
> +            arm_sctlr_b(env) ||
> +#endif
> +                ((env->uncached_cpsr & CPSR_E) ? 1 : 0);
>      }

This doesn't seem quite right -- for system emulation we currently
pick MO_BE or MO_LE based on the TB flag which is set according
to (arm_cpu_is_big_endian(env). So if we ignore SCTLR.B in
system mode then we'll still try to do LE accesses.

>      cur_el = arm_current_el(env);

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 13/17] arm: linux-user: don't set CPSR.E in BE32 mode
  2016-01-19 17:26   ` Peter Maydell
@ 2016-01-19 17:35     ` Peter Maydell
  2016-02-27 22:22       ` Peter Crosthwaite
  0 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 17:35 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 19 January 2016 at 17:26, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepeter@gmail.com> wrote:
>> Don't set CPSR.E for BE32 linux-user mode. As linux-user mode models
>> BE32, using normal BE (and system mode will not), a special case is
>> needed for user-mode where if sctlr.b is set, the CPU identifies as BE.
>>
>> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
>> ---
>>
>>  linux-user/main.c |  2 --
>>  target-arm/cpu.h  | 12 +++++++++++-
>>  2 files changed, 11 insertions(+), 3 deletions(-)
>>
>> diff --git a/linux-user/main.c b/linux-user/main.c
>> index d481458..60375fb 100644
>> --- a/linux-user/main.c
>> +++ b/linux-user/main.c
>> @@ -4496,8 +4496,6 @@ int main(int argc, char **argv, char **envp)
>>              env->uncached_cpsr |= CPSR_E;
>>          } else {
>>              env->cp15.sctlr_el[1] |= SCTLR_B;
>> -            /* We model BE32 as regular BE, so set CPSR_E */
>> -            env->uncached_cpsr |= CPSR_E;
>
> ...this is undoing what we just did in the previous patch and
> which I reviewed as being the wrong thing there...
>
>>          }
>>  #endif
>>      }
>> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
>> index 3edd56b..96b1e99 100644
>> --- a/target-arm/cpu.h
>> +++ b/target-arm/cpu.h
>> @@ -1812,7 +1812,17 @@ static bool arm_cpu_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 user mode, BE32 data accesses are just modelled as
>> +             * regular BE access. In system mode, BE32 is modelled as
>> +             * little endian, with the appropriate address translations on
>> +             * non-word accesses. So sctlr.b only affects overall
>> +             * endianness in user mode
>> +             */
>> +            arm_sctlr_b(env) ||
>> +#endif
>> +                ((env->uncached_cpsr & CPSR_E) ? 1 : 0);
>>      }
>
> This doesn't seem quite right -- for system emulation we currently
> pick MO_BE or MO_LE based on the TB flag which is set according
> to (arm_cpu_is_big_endian(env). So if we ignore SCTLR.B in
> system mode then we'll still try to do LE accesses.

Ah, no, looking at the next patch this is correct, it's just the
comment is a touch confusing. I suggest

 /* 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.
  */

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 14/17] target-arm: implement BE32 mode in system emulation
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 14/17] target-arm: implement BE32 mode in system emulation Peter Crosthwaite
@ 2016-01-19 17:39   ` Peter Maydell
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 17:39 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> From: Paolo Bonzini <pbonzini@redhat.com>
>
> System emulation only has a little-endian target; BE32 mode
> is implemented by adjusting the low bits of the address
> for every byte and halfword load and store.  64-bit accesses
> flip the low and high words.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> [PC changes:
>   * rebased against master (Jan 2016)
> ]
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---
>
>  target-arm/cpu.h       |  5 ++-
>  target-arm/translate.c | 86 +++++++++++++++++++++++++++++++++++++++++---------
>  2 files changed, 73 insertions(+), 18 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 96b1e99..5814019 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1925,9 +1925,8 @@ static inline bool bswap_code(bool sctlr_b)
>  #endif
>          sctlr_b;
>  #else
> -    /* We do not implement BE32 mode for system-mode emulation, but
> -     * anyway it would always do little-endian accesses with
> -     * TARGET_WORDS_BIGENDIAN = 0.
> +    /* All code access in ARM is little endian, and there are no loaders
> +     * doing swaps that need to be reversed
>       */
>      return 0;
>  #endif
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index 44c3ac9..2d80bb2 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -914,6 +914,12 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
>      }
>  }
>
> +#ifdef CONFIG_USER_ONLY
> +#define IS_USER_ONLY 1
> +#else
> +#define IS_USER_ONLY 0
> +#endif
> +
>  /* Abstractions of "generate code to do a guest load/store for
>   * AArch32", where a vaddr is always 32 bits (and is zero
>   * extended if we're a 64 bit core) and  data is also
> @@ -923,19 +929,35 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
>   */
>  #if TARGET_LONG_BITS == 32
>
> -#define DO_GEN_LD(SUFF, OPC)                                             \
> +#define DO_GEN_LD(SUFF, OPC, BE32_XOR)                                   \
>  static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,      \
>                                       TCGv_i32 addr, int index)           \
>  {                                                                        \
>      TCGMemOp opc = (OPC) | s->mo_endianness;                             \
> +    /* Not needed for user-mode BE32, where we use MO_BE instead.  */    \
> +    if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {                       \
> +        TCGv addr_be = tcg_temp_new();                                   \
> +        tcg_gen_xori_i32(addr_be, addr, BE32_XOR);                       \
> +        tcg_gen_qemu_ld_i32(val, addr_be, index, opc);                   \
> +        tcg_temp_free(addr_be);                                          \
> +        return;                                                          \
> +    }                                                                    \
>      tcg_gen_qemu_ld_i32(val, addr, index, opc);                          \
>  }
>
> -#define DO_GEN_ST(SUFF, OPC)                                             \
> +#define DO_GEN_ST(SUFF, OPC, BE32_XOR)                                   \
>  static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,      \
>                                       TCGv_i32 addr, int index)           \
>  {                                                                        \
>      TCGMemOp opc = (OPC) | s->mo_endianness;                             \
> +    /* Not needed for user-mode BE32, where we use MO_BE instead.  */    \
> +    if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {                       \
> +        TCGv addr_be = tcg_temp_new();                                   \
> +        tcg_gen_xori_i32(addr_be, addr, BE32_XOR);                       \
> +        tcg_gen_qemu_ld_i32(val, addr_be, index, opc);                   \

Cut-n-paste error -- this should be a store...

> +        tcg_temp_free(addr_be);                                          \
> +        return;                                                          \
> +    }                                                                    \
>      tcg_gen_qemu_st_i32(val, addr, index, opc);                          \
>  }
>

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 15/17] loader: add API to load elf header
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 15/17] loader: add API to load elf header Peter Crosthwaite
@ 2016-01-19 17:50   ` Peter Maydell
  2016-02-27 22:46     ` Peter Crosthwaite
  0 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 17:50 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> Add an API to load an elf header header from a file. Populates a
> buffer with the header contents, as well as a boolean for whether the
> elf is 64b or not. Both arguments are optional.
>
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---
>
>  hw/core/loader.c    | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/hw/loader.h |  1 +
>  2 files changed, 49 insertions(+)
>
> diff --git a/hw/core/loader.c b/hw/core/loader.c
> index 6b69852..28da8e2 100644
> --- a/hw/core/loader.c
> +++ b/hw/core/loader.c
> @@ -331,6 +331,54 @@ const char *load_elf_strerror(int error)
>      }
>  }
>
> +void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp)
> +{
> +    int fd;
> +    uint8_t e_ident[EI_NIDENT];
> +    size_t hdr_size, off = 0;
> +    bool is64l;
> +
> +    fd = open(filename, O_RDONLY | O_BINARY);
> +    if (fd < 0) {
> +        error_setg_errno(errp, errno, "Fail to open file");

"Failed" (also below).

I don't think we end up with the filename anywhere in the
error message; it would be helpful if we could include it.

> +        return;
> +    }
> +    if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident)) {
> +        error_setg_errno(errp, errno, "Fail to read file");
> +        goto fail;
> +    }
> +    if (e_ident[0] != ELFMAG0 ||
> +        e_ident[1] != ELFMAG1 ||
> +        e_ident[2] != ELFMAG2 ||
> +        e_ident[3] != ELFMAG3) {
> +        error_setg(errp, "Bad ELF magic");
> +        goto fail;
> +    }
> +
> +    is64l = e_ident[EI_CLASS] == ELFCLASS64;
> +    hdr_size = is64l ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr);
> +    if (is64) {
> +        *is64 = is64l;
> +    }
> +
> +    lseek(fd, 0, SEEK_SET);

You're not checking this lseek for failure (and you don't
need it anyway, because you could just copy the magic bytes
into *hdr and read four fewer bytes).

> +    while (hdr && off < hdr_size) {
> +        size_t br = read(fd, hdr + off, hdr_size - off);
> +        switch (br) {
> +        case 0:
> +            error_setg(errp, "File too short");
> +            goto fail;
> +        case -1:
> +            error_setg_errno(errp, errno, "Failed to read file");
> +            goto fail;
> +        }
> +        off += br;
> +    }
> +
> +fail:
> +    close(fd);
> +}
> +
>  /* return < 0 if error, otherwise the number of bytes loaded in memory */
>  int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
>               void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
> diff --git a/include/hw/loader.h b/include/hw/loader.h
> index f7b43ab..33067f8 100644
> --- a/include/hw/loader.h
> +++ b/include/hw/loader.h
> @@ -36,6 +36,7 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
>               void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
>               uint64_t *highaddr, int big_endian, int elf_machine,
>               int clear_lsb);
> +void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);

Doc comment, please.

>  int load_aout(const char *filename, hwaddr addr, int max_sz,
>                int bswap_needed, hwaddr target_page_size);
>  int load_uimage(const char *filename, hwaddr *ep,
> --
> 1.9.1

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf Peter Crosthwaite
@ 2016-01-19 17:53   ` Peter Maydell
  2016-02-27 23:14     ` Peter Crosthwaite
  0 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 17:53 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> Some CPUs are of an opposite data-endianness to other components in the
> system. Sometimes elfs have the data sections layed out with this CPU
> data-endianess accounting for when loaded via the CPU, byte swaps
> (relative to other system components) will occur.
>
> The leading example, is ARM's BE32 mode, which is is basically LE with
> address manipulation on half-word and byte accesses to access the
> hw/byte reversed address. This means that word data is invariant
> accross LE and BE32. This also means that instructions are still LE.
> The expectation is that the elf will be loaded via the CPU in this
> endianness scheme, which means the data in the elf is reversed at
> compile time.
>
> As QEMU loads via the system memory directly, rather than the CPU, we
> need a mechanism to reverse elf data endianness to implement this
> possibility.
>
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>

> diff --git a/include/hw/loader.h b/include/hw/loader.h
> index 33067f8..e542575 100644
> --- a/include/hw/loader.h
> +++ b/include/hw/loader.h
> @@ -35,7 +35,7 @@ const char *load_elf_strerror(int error);
>  int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
>               void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
>               uint64_t *highaddr, int big_endian, int elf_machine,
> -             int clear_lsb);
> +             int clear_lsb, int data_swab);
>  void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
>  int load_aout(const char *filename, hwaddr addr, int max_sz,
>                int bswap_needed, hwaddr target_page_size);

Can we have a doc comment so we have something that defines what
values data_swab accepts? (it's not just a bool).

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 17/17] arm: boot: Support big-endian elfs
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 17/17] arm: boot: Support big-endian elfs Peter Crosthwaite
@ 2016-01-19 18:06   ` Peter Maydell
  2016-02-27 23:59     ` Peter Crosthwaite
  0 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 18:06 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> Support ARM big-endian ELF files in system-mode emulation. When loading
> an elf, determine the endianness mode expected by the elf, and set the
> relevant CPU state accordingly.
>
> With this, big-endian modes are now fully supported via system-mode LE,
> so there is no need to restrict the elf loading to the TARGET
> endianness so the ifdeffery on TARGET_WORDS_BIGENDIAN goes away.
>
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---
>
>  hw/arm/boot.c        | 96 ++++++++++++++++++++++++++++++++++++++++++----------
>  include/hw/arm/arm.h |  9 +++++
>  2 files changed, 88 insertions(+), 17 deletions(-)
>
> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> index 0de4269..053c9e8 100644
> --- a/hw/arm/boot.c
> +++ b/hw/arm/boot.c
> @@ -465,9 +465,34 @@ static void do_cpu_reset(void *opaque)
>      cpu_reset(cs);
>      if (info) {
>          if (!info->is_linux) {
> +            int i;
>              /* Jump to the entry point.  */
>              uint64_t entry = info->entry;
>
> +            switch (info->endianness) {
> +            case ARM_ENDIANNESS_LE:
> +                env->cp15.sctlr_el[1] &= ~SCTLR_E0E;
> +                for (i = 1; i < 4; ++i) {
> +                    env->cp15.sctlr_el[i] &= ~SCTLR_EE;
> +                }
> +                env->uncached_cpsr &= ~CPSR_E;
> +                break;
> +            case ARM_ENDIANNESS_BE8:
> +                env->cp15.sctlr_el[1] |= SCTLR_E0E;
> +                for (i = 1; i < 4; ++i) {
> +                    env->cp15.sctlr_el[i] |= SCTLR_EE;
> +                }
> +                env->uncached_cpsr |= CPSR_E;
> +                break;
> +            case ARM_ENDIANNESS_BE32:
> +                env->cp15.sctlr_el[1] |= SCTLR_B;
> +                break;
> +            case ARM_ENDIANNESS_UNKNOWN:
> +                break; /* Board's decision */
> +            default:
> +                g_assert_not_reached();
> +            }

Do we really want this much magic for non-linux images? I would
expect that the image would be intended to run with whatever the
state the board puts the CPU in from reset (ie the CPU has suitable
QOM properties for its initial endianness state, corresponding to
real hardware reset-config signals like the A15's CFGEND/CFGTE).

> +
>              if (!env->aarch64) {
>                  env->thumb = info->entry & 1;
>                  entry &= 0xfffffffe;
> @@ -589,16 +614,23 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
>      int kernel_size;
>      int initrd_size;
>      int is_linux = 0;
> +
>      uint64_t elf_entry, elf_low_addr, elf_high_addr;
>      int elf_machine;
> +    bool elf_is64;
> +    union {
> +        Elf32_Ehdr h32;
> +        Elf64_Ehdr h64;
> +    } elf_header;
> +
>      hwaddr entry, kernel_load_offset;
> -    int big_endian;
>      static const ARMInsnFixup *primary_loader;
>      ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
>                                           notifier, notifier);
>      ARMCPU *cpu = n->cpu;
>      struct arm_boot_info *info =
>          container_of(n, struct arm_boot_info, load_kernel_notifier);
> +    Error *err = NULL;
>
>      /* The board code is not supposed to set secure_board_setup unless
>       * running its code in secure mode is actually possible, and KVM
> @@ -678,12 +710,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
>      if (info->nb_cpus == 0)
>          info->nb_cpus = 1;
>
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    big_endian = 1;
> -#else
> -    big_endian = 0;
> -#endif

Was this code ever built with TARGET_WORDS_BIGENDIAN defined?

> -
>      /* We want to put the initrd far enough into RAM that when the
>       * kernel is uncompressed it will not clobber the initrd. However
>       * on boards without much RAM we must ensure that we still leave
> @@ -698,16 +724,52 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
>          MIN(info->ram_size / 2, 128 * 1024 * 1024);
>
>      /* Assume that raw images are linux kernels, and ELF images are not.  */
> -    kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
> -                           &elf_low_addr, &elf_high_addr, big_endian,
> -                           elf_machine, 1, 0);
> -    if (kernel_size > 0 && have_dtb(info)) {
> -        /* If there is still some room left at the base of RAM, try and put
> -         * the DTB there like we do for images loaded with -bios or -pflash.
> -         */
> -        if (elf_low_addr > info->loader_start
> -            || elf_high_addr < info->loader_start) {
> -            /* Pass elf_low_addr as address limit to load_dtb if it may be
> +
> +    load_elf_hdr(info->kernel_filename, &elf_header, &elf_is64, &err);
> +
> +    if (!err) {
> +        int data_swab = 0;
> +        bool big_endian;
> +
> +        if (elf_is64) {
> +            big_endian = elf_header.h64.e_ident[EI_DATA] == ELFDATA2MSB;
> +            info->endianness = big_endian ? ARM_ENDIANNESS_BE8
> +                                          : ARM_ENDIANNESS_LE;
> +        } else {
> +            big_endian = elf_header.h32.e_ident[EI_DATA] == ELFDATA2MSB;
> +            if (big_endian) {
> +                if (bswap32(elf_header.h32.e_flags) & EF_ARM_BE8) {
> +                    info->endianness = ARM_ENDIANNESS_BE8;
> +                } else {
> +                    info->endianness = ARM_ENDIANNESS_BE32;
> +                    /* In BE32, the CPU has a different view of the per-byte
> +                     * address map than the rest of the system. BE32 elfs are
> +                     * organised such that they can be programmed through the
> +                     * CPUs per-word byte-reversed view of the world. QEMU
> +                     * however loads elfs independently of the CPU. So tell
> +                     * the elf loader to byte reverse the data for us.
> +                     */
> +                    data_swab = 2;
> +                }
> +            } else {
> +                info->endianness = ARM_ENDIANNESS_LE;
> +            }
> +        }
> +
> +        kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
> +                               &elf_low_addr, &elf_high_addr, big_endian,
> +                               elf_machine, 1, data_swab);
> +        if (kernel_size <= 0) {
> +            exit(1);
> +        }
> +
> +        if (have_dtb(info) && (elf_low_addr > info->loader_start ||
> +                               elf_high_addr < info->loader_start)) {
> +            /* If there is still some room left at the base of RAM, try and
> +             * put the DTB there like we do for images loaded with -bios or
> +             * -pflash.
> +             *
> +             * Pass elf_low_addr as address limit to load_dtb if it may be
>               * pointing into RAM, otherwise pass '0' (no limit)
>               */
>              if (elf_low_addr < info->loader_start) {

I think this change would be easier to read if we had a new
(static) function in this file load_arm_elf() which did the
"load header; figure out data_swab; load full elf file with
corresponding swab value". Then the change to this function would
just be a one-liner turning the load_elf() call into load_arm_elf().

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (16 preceding siblings ...)
  2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 17/17] arm: boot: Support big-endian elfs Peter Crosthwaite
@ 2016-01-19 18:06 ` Peter Maydell
  2016-03-01  5:27 ` Stefan Weil
  18 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2016-01-19 18:06 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 18 January 2016 at 07:12, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> Hi All,
>
> This patch series adds system-mode big-endian support for ARM. It also
> implements the setend instruction, and loading of BE binaries even in
> LE emulation mode.
>
> Based on Paolo's original work. I have moved all the BE32 related work
> to the back of the series. Multiple parties are interested in the BE8
> work just on its own, so that could potentially be merged w/o BE32.
> PMM requested BE32 be at least thought out architecturally, so this
> series sees BE32 functionality through.
>
> I have tested all of LE. BE8 and BE32 in both linux-user mode (for
> regressions) and system mode (BE8 and BE32 are new here).
> My test application is here, the README gives some example command
> lines you can run:
>
> https://github.com/pcrost/arm-be-test

Thanks for picking this up again. I've sent out my review comments on it now.

-- PMM

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

* Re: [Qemu-devel] [PATCH v1 04/17] target-arm: implement SCTLR.EE
  2016-01-19 15:58   ` Peter Maydell
@ 2016-02-27 21:56     ` Peter Crosthwaite
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-02-27 21:56 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, Alistair Francis, sridhar kulkarni, qemu-arm,
	Paolo Bonzini, Piotr Król

On Tue, Jan 19, 2016 at 7:58 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepeter@gmail.com> wrote:
>> From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>>
>> Implement SCTLR.EE bit which controls data endianess for exceptions
>> and page table translations. SCTLR.EE is mirrored to the CPSR.E bit
>> on exception entry.
>>
>> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>> ---
>>
>>  target-arm/helper.c | 42 ++++++++++++++++++++++++++++++++----------
>>  1 file changed, 32 insertions(+), 10 deletions(-)
>>
>> diff --git a/target-arm/helper.c b/target-arm/helper.c
>> index 59d5a41..afac1b2 100644
>> --- a/target-arm/helper.c
>> +++ b/target-arm/helper.c
>> @@ -5889,7 +5889,10 @@ void arm_cpu_do_interrupt(CPUState *cs)
>>      /* Clear IT bits.  */
>>      env->condexec_bits = 0;
>>      /* Switch to the new mode, and to the correct instruction set.  */
>> -    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
>> +    env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_M)) | new_mode;
>
> Why change this line?
>

Reverted

>> +    /* Set new mode endianess */
>
> "endianness"
>

Fixed

>> +    env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_E)) |
>> +        (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE ? CPSR_E : 0);
>
> This is a bit confusing. I think just splitting it into
> multiple statements would help:
>    env->uncached_cpsr &= ~CPSR_E;
>    if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
>        env->uncached_cpsr |= CPSR_E;
>    }
>

Fixed.

>>      env->daif |= mask;
>>      /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
>>       * and we should just guard the thumb mode on V4 */
>> @@ -5958,6 +5961,12 @@ static inline bool regime_translation_disabled(CPUARMState *env,
>>      return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
>>  }
>>
>> +static inline bool regime_translation_big_endian(CPUARMState *env,
>> +                                                 ARMMMUIdx mmu_idx)
>> +{
>> +    return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
>> +}
>> +
>>  /* Return the TCR controlling this translation regime */
>>  static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
>>  {
>> @@ -6263,7 +6272,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
>>   */
>>  static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
>>                              ARMMMUIdx mmu_idx, uint32_t *fsr,
>> -                            ARMMMUFaultInfo *fi)
>> +                            ARMMMUFaultInfo *fi, bool be)
>>  {
>>      ARMCPU *cpu = ARM_CPU(cs);
>>      CPUARMState *env = &cpu->env;
>> @@ -6274,12 +6283,16 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
>>      if (fi->s1ptw) {
>>          return 0;
>>      }
>> -    return address_space_ldl(cs->as, addr, attrs, NULL);
>> +    if (be) {
>> +        return address_space_ldl_be(cs->as, addr, attrs, NULL);
>> +    } else {
>> +        return address_space_ldl_le(cs->as, addr, attrs, NULL);
>> +    }
>>  }
>
> Why not just call regime_translation_big_endian() inside arm_ldl_ptw()
> and arm_ldq_ptw(), rather than having every call site making the call
> and passing in the result?
>

Fixed.

> PS: this patch will conflict with the multi-ases series but only
> fairly trivially.
>

Resolved.

Regards,
Peter

> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header
  2016-01-19 16:11   ` Peter Maydell
@ 2016-02-27 22:02     ` Peter Crosthwaite
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-02-27 22:02 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, Alistair Francis, sridhar kulkarni, qemu-arm,
	Paolo Bonzini, Piotr Król

On Tue, Jan 19, 2016 at 8:11 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepeter@gmail.com> wrote:
>> From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>>
>> There is a CPU data endianness test that is used to drive the
>> virtio_big_endian test.
>>
>> Move this up to the header so it can be more generally used for endian
>> tests. The KVM specific cpu_syncronize_state call is left behind in the
>> virtio specific function.
>>
>> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>> ---
>>
>>  target-arm/cpu.c | 19 +++----------------
>>  target-arm/cpu.h | 19 +++++++++++++++++++
>>  2 files changed, 22 insertions(+), 16 deletions(-)
>>
>> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
>> index 35a1f12..d3b73bf 100644
>> --- a/target-arm/cpu.c
>> +++ b/target-arm/cpu.c
>> @@ -368,26 +368,13 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
>>  #endif
>>  }
>>
>> -static bool arm_cpu_is_big_endian(CPUState *cs)
>> +static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
>>  {
>>      ARMCPU *cpu = ARM_CPU(cs);
>>      CPUARMState *env = &cpu->env;
>> -    int cur_el;
>>
>>      cpu_synchronize_state(cs);
>> -
>> -    /* In 32bit guest endianness is determined by looking at CPSR's E bit */
>> -    if (!is_a64(env)) {
>> -        return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
>> -    }
>> -
>> -    cur_el = arm_current_el(env);
>> -
>> -    if (cur_el == 0) {
>> -        return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
>> -    }
>> -
>> -    return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
>> +    return arm_cpu_is_big_endian(env);
>>  }
>>
>>  #endif
>> @@ -1420,7 +1407,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>>      cc->do_unaligned_access = arm_cpu_do_unaligned_access;
>>      cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
>>      cc->vmsd = &vmstate_arm_cpu;
>> -    cc->virtio_is_big_endian = arm_cpu_is_big_endian;
>> +    cc->virtio_is_big_endian = arm_cpu_virtio_is_big_endian;
>>  #endif
>>      cc->gdb_num_core_regs = 26;
>>      cc->gdb_core_xml_file = "arm-core.xml";
>> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
>> index f83070a..54675c7 100644
>> --- a/target-arm/cpu.h
>> +++ b/target-arm/cpu.h
>> @@ -1795,6 +1795,25 @@ static inline bool arm_singlestep_active(CPUARMState *env)
>>          && arm_generate_debug_exceptions(env);
>>  }
>>
>> +/* Return true if the processor is in big-endian mode. */
>> +static bool arm_cpu_is_big_endian(CPUARMState *env)
>> +{
>
> No problems code-wise, but can we call the function
> arm_cpu_data_is_big_endian() or something?

Fixed.

Regards,
Peter

> This is returning the
> endianness to use for data accesses; there isn't an overall
> "big-endian mode" that affects everything except for the
> obsolete BE32.
>
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 10/17] target-arm: implement setend
  2016-01-19 16:29   ` Peter Maydell
@ 2016-02-27 22:14     ` Peter Crosthwaite
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-02-27 22:14 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On Tue, Jan 19, 2016 at 8:29 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepeter@gmail.com> wrote:
>> From: Paolo Bonzini <pbonzini@redhat.com>
>>
>> Since this is not a high-performance path, just use a helper to
>> flip the E bit and force a lookup in the hash table since the
>> flags have changed.
>>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
>> ---
>>
>>  target-arm/helper.h    |  1 +
>>  target-arm/op_helper.c |  5 +++++
>>  target-arm/translate.c | 16 ++++++++--------
>>  3 files changed, 14 insertions(+), 8 deletions(-)
>>
>> diff --git a/target-arm/helper.h b/target-arm/helper.h
>> index c2a85c7..2315a9c 100644
>> --- a/target-arm/helper.h
>> +++ b/target-arm/helper.h
>> @@ -48,6 +48,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
>>                     i32, i32, i32, i32)
>>  DEF_HELPER_2(exception_internal, void, env, i32)
>>  DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
>> +DEF_HELPER_1(setend, void, env)
>>  DEF_HELPER_1(wfi, void, env)
>>  DEF_HELPER_1(wfe, void, env)
>>  DEF_HELPER_1(yield, void, env)
>> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
>> index e42d287..2a4bc67 100644
>> --- a/target-arm/op_helper.c
>> +++ b/target-arm/op_helper.c
>> @@ -295,6 +295,11 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
>>      return res;
>>  }
>>
>> +void HELPER(setend)(CPUARMState *env)
>> +{
>> +    env->uncached_cpsr ^= CPSR_E;
>> +}
>> +
>>  /* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
>>   * The function returns the target EL (1-3) if the instruction is to be trapped;
>>   * otherwise it returns 0 indicating it is not trapped.
>> diff --git a/target-arm/translate.c b/target-arm/translate.c
>> index cb925ef..192a5d6 100644
>> --- a/target-arm/translate.c
>> +++ b/target-arm/translate.c
>> @@ -7726,10 +7726,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
>>          if ((insn & 0x0ffffdff) == 0x01010000) {
>>              ARCH(6);
>>              /* setend */
>> -            if (((insn >> 9) & 1) != s->bswap_code) {
>> -                /* Dynamic endianness switching not implemented. */
>> -                qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
>> -                goto illegal_op;
>> +            if (((insn >> 9) & 1) != !!(s->mo_endianness == MO_BE)) {
>> +                gen_helper_setend(cpu_env);
>> +                gen_set_pc_im(s, s->pc);
>> +                s->is_jmp = DISAS_JUMP;
>
> Rather than manually calling set_pc_im and using DISAS_JUMP, better
> to use DISAS_UPDATE, which will do the gen_set_pc_im() call for you.
>
> (Ditto in the other hunk.)
>

Fixed.

Regards,
Peter

> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 13/17] arm: linux-user: don't set CPSR.E in BE32 mode
  2016-01-19 17:35     ` Peter Maydell
@ 2016-02-27 22:22       ` Peter Crosthwaite
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-02-27 22:22 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On Tue, Jan 19, 2016 at 9:35 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 19 January 2016 at 17:26, Peter Maydell <peter.maydell@linaro.org> wrote:
>> On 18 January 2016 at 07:12, Peter Crosthwaite
>> <crosthwaitepeter@gmail.com> wrote:
>>> Don't set CPSR.E for BE32 linux-user mode. As linux-user mode models
>>> BE32, using normal BE (and system mode will not), a special case is
>>> needed for user-mode where if sctlr.b is set, the CPU identifies as BE.
>>>
>>> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
>>> ---
>>>
>>>  linux-user/main.c |  2 --
>>>  target-arm/cpu.h  | 12 +++++++++++-
>>>  2 files changed, 11 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/linux-user/main.c b/linux-user/main.c
>>> index d481458..60375fb 100644
>>> --- a/linux-user/main.c
>>> +++ b/linux-user/main.c
>>> @@ -4496,8 +4496,6 @@ int main(int argc, char **argv, char **envp)
>>>              env->uncached_cpsr |= CPSR_E;
>>>          } else {
>>>              env->cp15.sctlr_el[1] |= SCTLR_B;
>>> -            /* We model BE32 as regular BE, so set CPSR_E */
>>> -            env->uncached_cpsr |= CPSR_E;
>>
>> ...this is undoing what we just did in the previous patch and
>> which I reviewed as being the wrong thing there...
>>
>>>          }
>>>  #endif
>>>      }
>>> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
>>> index 3edd56b..96b1e99 100644
>>> --- a/target-arm/cpu.h
>>> +++ b/target-arm/cpu.h
>>> @@ -1812,7 +1812,17 @@ static bool arm_cpu_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 user mode, BE32 data accesses are just modelled as
>>> +             * regular BE access. In system mode, BE32 is modelled as
>>> +             * little endian, with the appropriate address translations on
>>> +             * non-word accesses. So sctlr.b only affects overall
>>> +             * endianness in user mode
>>> +             */
>>> +            arm_sctlr_b(env) ||
>>> +#endif
>>> +                ((env->uncached_cpsr & CPSR_E) ? 1 : 0);
>>>      }
>>
>> This doesn't seem quite right -- for system emulation we currently
>> pick MO_BE or MO_LE based on the TB flag which is set according
>> to (arm_cpu_is_big_endian(env). So if we ignore SCTLR.B in
>> system mode then we'll still try to do LE accesses.
>
> Ah, no, looking at the next patch this is correct, it's just the
> comment is a touch confusing. I suggest
>
>  /* 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.
>   */
>

Comment updated.

Regards,
Peter

> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 15/17] loader: add API to load elf header
  2016-01-19 17:50   ` Peter Maydell
@ 2016-02-27 22:46     ` Peter Crosthwaite
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-02-27 22:46 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On Tue, Jan 19, 2016 at 9:50 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepeter@gmail.com> wrote:
>> Add an API to load an elf header header from a file. Populates a
>> buffer with the header contents, as well as a boolean for whether the
>> elf is 64b or not. Both arguments are optional.
>>
>> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
>> ---
>>
>>  hw/core/loader.c    | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/hw/loader.h |  1 +
>>  2 files changed, 49 insertions(+)
>>
>> diff --git a/hw/core/loader.c b/hw/core/loader.c
>> index 6b69852..28da8e2 100644
>> --- a/hw/core/loader.c
>> +++ b/hw/core/loader.c
>> @@ -331,6 +331,54 @@ const char *load_elf_strerror(int error)
>>      }
>>  }
>>
>> +void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp)
>> +{
>> +    int fd;
>> +    uint8_t e_ident[EI_NIDENT];
>> +    size_t hdr_size, off = 0;
>> +    bool is64l;
>> +
>> +    fd = open(filename, O_RDONLY | O_BINARY);
>> +    if (fd < 0) {
>> +        error_setg_errno(errp, errno, "Fail to open file");
>
> "Failed" (also below).
>

Fixed (x2).

> I don't think we end up with the filename anywhere in the
> error message; it would be helpful if we could include it.
>

Fixed (x4)

>> +        return;
>> +    }
>> +    if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident)) {
>> +        error_setg_errno(errp, errno, "Fail to read file");
>> +        goto fail;
>> +    }
>> +    if (e_ident[0] != ELFMAG0 ||
>> +        e_ident[1] != ELFMAG1 ||
>> +        e_ident[2] != ELFMAG2 ||
>> +        e_ident[3] != ELFMAG3) {
>> +        error_setg(errp, "Bad ELF magic");
>> +        goto fail;
>> +    }
>> +
>> +    is64l = e_ident[EI_CLASS] == ELFCLASS64;
>> +    hdr_size = is64l ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr);
>> +    if (is64) {
>> +        *is64 = is64l;
>> +    }
>> +
>> +    lseek(fd, 0, SEEK_SET);
>
> You're not checking this lseek for failure (and you don't
> need it anyway, because you could just copy the magic bytes
> into *hdr and read four fewer bytes).
>

OK, so I have optimised it away. What I am doing now is always reading
to straight to hdr[], and if the caller passes hdr == NULL, then hdr
is set to a local buffer (and the full header read is still skipped as
per current logic).

>> +    while (hdr && off < hdr_size) {
>> +        size_t br = read(fd, hdr + off, hdr_size - off);
>> +        switch (br) {
>> +        case 0:
>> +            error_setg(errp, "File too short");
>> +            goto fail;
>> +        case -1:
>> +            error_setg_errno(errp, errno, "Failed to read file");
>> +            goto fail;
>> +        }
>> +        off += br;
>> +    }
>> +
>> +fail:
>> +    close(fd);
>> +}
>> +
>>  /* return < 0 if error, otherwise the number of bytes loaded in memory */
>>  int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
>>               void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
>> diff --git a/include/hw/loader.h b/include/hw/loader.h
>> index f7b43ab..33067f8 100644
>> --- a/include/hw/loader.h
>> +++ b/include/hw/loader.h
>> @@ -36,6 +36,7 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
>>               void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
>>               uint64_t *highaddr, int big_endian, int elf_machine,
>>               int clear_lsb);
>> +void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
>
> Doc comment, please.
>

Added:

+
+/** load_elf_hdr:
+ * @filename: Path of ELF file
+ * @hdr: Buffer to populate with header data. Header data will not be
+ * filled if set to NULL.
+ * @is64: Set to true if the ELF is 64bit. Ignored if set to NULL
+ * @errp: Populated with an error in failure cases
+ *
+ * Inspect as ELF file's header. Read its full header contents into a
+ * buffer and/or determine if the ELF is 64bit.
+ */


Regards,
Peter

>>  int load_aout(const char *filename, hwaddr addr, int max_sz,
>>                int bswap_needed, hwaddr target_page_size);
>>  int load_uimage(const char *filename, hwaddr *ep,
>> --
>> 1.9.1
>
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf
  2016-01-19 17:53   ` Peter Maydell
@ 2016-02-27 23:14     ` Peter Crosthwaite
  2016-02-28 15:28       ` Peter Maydell
  0 siblings, 1 reply; 51+ messages in thread
From: Peter Crosthwaite @ 2016-02-27 23:14 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On Tue, Jan 19, 2016 at 9:53 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepeter@gmail.com> wrote:
>> Some CPUs are of an opposite data-endianness to other components in the
>> system. Sometimes elfs have the data sections layed out with this CPU
>> data-endianess accounting for when loaded via the CPU, byte swaps
>> (relative to other system components) will occur.
>>
>> The leading example, is ARM's BE32 mode, which is is basically LE with
>> address manipulation on half-word and byte accesses to access the
>> hw/byte reversed address. This means that word data is invariant
>> accross LE and BE32. This also means that instructions are still LE.
>> The expectation is that the elf will be loaded via the CPU in this
>> endianness scheme, which means the data in the elf is reversed at
>> compile time.
>>
>> As QEMU loads via the system memory directly, rather than the CPU, we
>> need a mechanism to reverse elf data endianness to implement this
>> possibility.
>>
>> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
>
>> diff --git a/include/hw/loader.h b/include/hw/loader.h
>> index 33067f8..e542575 100644
>> --- a/include/hw/loader.h
>> +++ b/include/hw/loader.h
>> @@ -35,7 +35,7 @@ const char *load_elf_strerror(int error);
>>  int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
>>               void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
>>               uint64_t *highaddr, int big_endian, int elf_machine,
>> -             int clear_lsb);
>> +             int clear_lsb, int data_swab);
>>  void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
>>  int load_aout(const char *filename, hwaddr addr, int max_sz,
>>                int bswap_needed, hwaddr target_page_size);
>
> Can we have a doc comment so we have something that defines what
> values data_swab accepts? (it's not just a bool).
>

This is difficult to capture without writing to whole documentation
for load_elf. So here goes:

/** load_elf:
 * @filename: Path of ELF file
 * @translate_fn: optional function to translate load addresses
 * @translate_opaque: opaque data passed to @translate_fn
 * @pentry: Populated with program entry point. Ignored if NULL.
 * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
 * @highaddr: Populated with highest loaded address. Ignored if NULL.
 * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
 * @elf_machine: Expected ELF machine type
 * @clear_lsb: Set to mask off LSB of addresses (Some arch's use this
               for non-address data)
 * @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
 *             for swapping bytes within halfwords, 2 for bytes within
 *             words and 3 for within doublewords.
 *
 * Load an ELF file's contents to the emulated systems address space.
 * Clients may optionally specify a callback to perform address
 * translations. @pentry, @lowaddr and @highaddr are optional pointers
 * which will be populated with various load information. @bigendian and
 * @elf_machine give the expected endianness and machine for the ELF the
 * load will fail it the target ELF does not match. Some architectures
 * have some arch-specific behaviours that come into effect when their
 * particular values for @elf_machine are set.
 */

Regards,
Peter

> Otherwise
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
>
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 17/17] arm: boot: Support big-endian elfs
  2016-01-19 18:06   ` Peter Maydell
@ 2016-02-27 23:59     ` Peter Crosthwaite
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-02-27 23:59 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On Tue, Jan 19, 2016 at 10:06 AM, Peter Maydell
<peter.maydell@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepeter@gmail.com> wrote:
>> Support ARM big-endian ELF files in system-mode emulation. When loading
>> an elf, determine the endianness mode expected by the elf, and set the
>> relevant CPU state accordingly.
>>
>> With this, big-endian modes are now fully supported via system-mode LE,
>> so there is no need to restrict the elf loading to the TARGET
>> endianness so the ifdeffery on TARGET_WORDS_BIGENDIAN goes away.
>>
>> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
>> ---
>>
>>  hw/arm/boot.c        | 96 ++++++++++++++++++++++++++++++++++++++++++----------
>>  include/hw/arm/arm.h |  9 +++++
>>  2 files changed, 88 insertions(+), 17 deletions(-)
>>
>> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
>> index 0de4269..053c9e8 100644
>> --- a/hw/arm/boot.c
>> +++ b/hw/arm/boot.c
>> @@ -465,9 +465,34 @@ static void do_cpu_reset(void *opaque)
>>      cpu_reset(cs);
>>      if (info) {
>>          if (!info->is_linux) {
>> +            int i;
>>              /* Jump to the entry point.  */
>>              uint64_t entry = info->entry;
>>
>> +            switch (info->endianness) {
>> +            case ARM_ENDIANNESS_LE:
>> +                env->cp15.sctlr_el[1] &= ~SCTLR_E0E;
>> +                for (i = 1; i < 4; ++i) {
>> +                    env->cp15.sctlr_el[i] &= ~SCTLR_EE;
>> +                }
>> +                env->uncached_cpsr &= ~CPSR_E;
>> +                break;
>> +            case ARM_ENDIANNESS_BE8:
>> +                env->cp15.sctlr_el[1] |= SCTLR_E0E;
>> +                for (i = 1; i < 4; ++i) {
>> +                    env->cp15.sctlr_el[i] |= SCTLR_EE;
>> +                }
>> +                env->uncached_cpsr |= CPSR_E;
>> +                break;
>> +            case ARM_ENDIANNESS_BE32:
>> +                env->cp15.sctlr_el[1] |= SCTLR_B;
>> +                break;
>> +            case ARM_ENDIANNESS_UNKNOWN:
>> +                break; /* Board's decision */
>> +            default:
>> +                g_assert_not_reached();
>> +            }
>
> Do we really want this much magic for non-linux images?

I think so ...

>  I would
> expect that the image would be intended to run with whatever the
> state the board puts the CPU in from reset (ie the CPU has suitable
> QOM properties for its initial endianness state, corresponding to
> real hardware reset-config signals like the A15's CFGEND/CFGTE).
>

As with this you can handle two use cases:

1: Elfs for firmware development
2: Elfs for a real-world loadable guest.

Firmware elfs should match the hardwired (QOM properties) settings
anyway, but the more interesting case is the real-world loadable guest
ELF. That is, you have some elf-capable bootloader in real HW which
will DTRT based on the elf header before handoff. This will emulate
that case without needing to demote your elf to raw binary data (and
then explicitly load your bootloader).

>> +
>>              if (!env->aarch64) {
>>                  env->thumb = info->entry & 1;
>>                  entry &= 0xfffffffe;
>> @@ -589,16 +614,23 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
>>      int kernel_size;
>>      int initrd_size;
>>      int is_linux = 0;
>> +
>>      uint64_t elf_entry, elf_low_addr, elf_high_addr;
>>      int elf_machine;
>> +    bool elf_is64;
>> +    union {
>> +        Elf32_Ehdr h32;
>> +        Elf64_Ehdr h64;
>> +    } elf_header;
>> +
>>      hwaddr entry, kernel_load_offset;
>> -    int big_endian;
>>      static const ARMInsnFixup *primary_loader;
>>      ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
>>                                           notifier, notifier);
>>      ARMCPU *cpu = n->cpu;
>>      struct arm_boot_info *info =
>>          container_of(n, struct arm_boot_info, load_kernel_notifier);
>> +    Error *err = NULL;
>>
>>      /* The board code is not supposed to set secure_board_setup unless
>>       * running its code in secure mode is actually possible, and KVM
>> @@ -678,12 +710,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
>>      if (info->nb_cpus == 0)
>>          info->nb_cpus = 1;
>>
>> -#ifdef TARGET_WORDS_BIGENDIAN
>> -    big_endian = 1;
>> -#else
>> -    big_endian = 0;
>> -#endif
>
> Was this code ever built with TARGET_WORDS_BIGENDIAN defined?
>

No I believe not. I can do the dead code cleanup as a separate patch?

>> -
>>      /* We want to put the initrd far enough into RAM that when the
>>       * kernel is uncompressed it will not clobber the initrd. However
>>       * on boards without much RAM we must ensure that we still leave
>> @@ -698,16 +724,52 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
>>          MIN(info->ram_size / 2, 128 * 1024 * 1024);
>>
>>      /* Assume that raw images are linux kernels, and ELF images are not.  */
>> -    kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
>> -                           &elf_low_addr, &elf_high_addr, big_endian,
>> -                           elf_machine, 1, 0);
>> -    if (kernel_size > 0 && have_dtb(info)) {
>> -        /* If there is still some room left at the base of RAM, try and put
>> -         * the DTB there like we do for images loaded with -bios or -pflash.
>> -         */
>> -        if (elf_low_addr > info->loader_start
>> -            || elf_high_addr < info->loader_start) {
>> -            /* Pass elf_low_addr as address limit to load_dtb if it may be
>> +
>> +    load_elf_hdr(info->kernel_filename, &elf_header, &elf_is64, &err);
>> +
>> +    if (!err) {
>> +        int data_swab = 0;
>> +        bool big_endian;
>> +
>> +        if (elf_is64) {
>> +            big_endian = elf_header.h64.e_ident[EI_DATA] == ELFDATA2MSB;
>> +            info->endianness = big_endian ? ARM_ENDIANNESS_BE8
>> +                                          : ARM_ENDIANNESS_LE;
>> +        } else {
>> +            big_endian = elf_header.h32.e_ident[EI_DATA] == ELFDATA2MSB;
>> +            if (big_endian) {
>> +                if (bswap32(elf_header.h32.e_flags) & EF_ARM_BE8) {
>> +                    info->endianness = ARM_ENDIANNESS_BE8;
>> +                } else {
>> +                    info->endianness = ARM_ENDIANNESS_BE32;
>> +                    /* In BE32, the CPU has a different view of the per-byte
>> +                     * address map than the rest of the system. BE32 elfs are
>> +                     * organised such that they can be programmed through the
>> +                     * CPUs per-word byte-reversed view of the world. QEMU
>> +                     * however loads elfs independently of the CPU. So tell
>> +                     * the elf loader to byte reverse the data for us.
>> +                     */
>> +                    data_swab = 2;
>> +                }
>> +            } else {
>> +                info->endianness = ARM_ENDIANNESS_LE;
>> +            }
>> +        }
>> +
>> +        kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
>> +                               &elf_low_addr, &elf_high_addr, big_endian,
>> +                               elf_machine, 1, data_swab);
>> +        if (kernel_size <= 0) {
>> +            exit(1);
>> +        }
>> +
>> +        if (have_dtb(info) && (elf_low_addr > info->loader_start ||
>> +                               elf_high_addr < info->loader_start)) {
>> +            /* If there is still some room left at the base of RAM, try and
>> +             * put the DTB there like we do for images loaded with -bios or
>> +             * -pflash.
>> +             *
>> +             * Pass elf_low_addr as address limit to load_dtb if it may be
>>               * pointing into RAM, otherwise pass '0' (no limit)
>>               */
>>              if (elf_low_addr < info->loader_start) {
>
> I think this change would be easier to read if we had a new
> (static) function in this file load_arm_elf() which did the
> "load header; figure out data_swab; load full elf file with
> corresponding swab value". Then the change to this function would
> just be a one-liner turning the load_elf() call into load_arm_elf().
>

Agree, new diff looks better.

"arm_load_elf" would be more consistent with surrounding code:

+static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
+                             uint64_t *lowaddr, uint64_t *highaddr,
+                             int elf_machine)

load_elf arguments that are constant for ARM (like translate_fn and
clear_lsb) are dropped from the new function prototype and just
hardcoded in arm_load_elf().

Regards,
Peter

> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf
  2016-02-27 23:14     ` Peter Crosthwaite
@ 2016-02-28 15:28       ` Peter Maydell
  2016-02-28 20:16         ` Peter Crosthwaite
  0 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2016-02-28 15:28 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On 27 February 2016 at 23:14, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> On Tue, Jan 19, 2016 at 9:53 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
>> Can we have a doc comment so we have something that defines what
>> values data_swab accepts? (it's not just a bool).
>>
>
> This is difficult to capture without writing to whole documentation
> for load_elf. So here goes:

Thanks; a couple of typos below, but otherwise looks good.


> /** load_elf:
>  * @filename: Path of ELF file
>  * @translate_fn: optional function to translate load addresses
>  * @translate_opaque: opaque data passed to @translate_fn
>  * @pentry: Populated with program entry point. Ignored if NULL.
>  * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
>  * @highaddr: Populated with highest loaded address. Ignored if NULL.
>  * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
>  * @elf_machine: Expected ELF machine type
>  * @clear_lsb: Set to mask off LSB of addresses (Some arch's use this

Can we just write out "architectures" here?

>                for non-address data)
>  * @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
>  *             for swapping bytes within halfwords, 2 for bytes within
>  *             words and 3 for within doublewords.
>  *
>  * Load an ELF file's contents to the emulated systems address space.

"system's"

>  * Clients may optionally specify a callback to perform address
>  * translations. @pentry, @lowaddr and @highaddr are optional pointers
>  * which will be populated with various load information. @bigendian and
>  * @elf_machine give the expected endianness and machine for the ELF the
>  * load will fail it the target ELF does not match. Some architectures

"if"

>  * have some arch-specific behaviours that come into effect when their

"architecture"

>  * particular values for @elf_machine are set.
>  */

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf
  2016-02-28 15:28       ` Peter Maydell
@ 2016-02-28 20:16         ` Peter Crosthwaite
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-02-28 20:16 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, QEMU Developers, Alistair Francis,
	sridhar kulkarni, qemu-arm, Paolo Bonzini, Piotr Król

On Sun, Feb 28, 2016 at 7:28 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 27 February 2016 at 23:14, Peter Crosthwaite
> <crosthwaitepeter@gmail.com> wrote:
>> On Tue, Jan 19, 2016 at 9:53 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
>>> Can we have a doc comment so we have something that defines what
>>> values data_swab accepts? (it's not just a bool).
>>>
>>
>> This is difficult to capture without writing to whole documentation
>> for load_elf. So here goes:
>
> Thanks; a couple of typos below, but otherwise looks good.
>
>
>> /** load_elf:
>>  * @filename: Path of ELF file
>>  * @translate_fn: optional function to translate load addresses
>>  * @translate_opaque: opaque data passed to @translate_fn
>>  * @pentry: Populated with program entry point. Ignored if NULL.
>>  * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
>>  * @highaddr: Populated with highest loaded address. Ignored if NULL.
>>  * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
>>  * @elf_machine: Expected ELF machine type
>>  * @clear_lsb: Set to mask off LSB of addresses (Some arch's use this
>
> Can we just write out "architectures" here?
>
>>                for non-address data)
>>  * @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
>>  *             for swapping bytes within halfwords, 2 for bytes within
>>  *             words and 3 for within doublewords.
>>  *
>>  * Load an ELF file's contents to the emulated systems address space.
>
> "system's"
>
>>  * Clients may optionally specify a callback to perform address
>>  * translations. @pentry, @lowaddr and @highaddr are optional pointers
>>  * which will be populated with various load information. @bigendian and
>>  * @elf_machine give the expected endianness and machine for the ELF the
>>  * load will fail it the target ELF does not match. Some architectures
>
> "if"
>
>>  * have some arch-specific behaviours that come into effect when their
>
> "architecture"
>

All fixed. Thanks for the pre-review.

Regards,
Peter

>>  * particular values for @elf_machine are set.
>>  */
>
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support
  2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
                   ` (17 preceding siblings ...)
  2016-01-19 18:06 ` [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Maydell
@ 2016-03-01  5:27 ` Stefan Weil
  2016-03-01 18:26   ` Peter Crosthwaite
  2016-03-01 18:43   ` Peter Crosthwaite
  18 siblings, 2 replies; 51+ messages in thread
From: Stefan Weil @ 2016-03-01  5:27 UTC (permalink / raw)
  To: Peter Crosthwaite, qemu-devel
  Cc: peter.maydell, Andrew Baumann, alistair.francis, sridhar_kulk,
	qemu-arm, pbonzini, piotr.krol

[-- Attachment #1: Type: text/plain, Size: 1174 bytes --]

Am 18.01.2016 um 08:12 schrieb Peter Crosthwaite:
> Hi All,
>
> This patch series adds system-mode big-endian support for ARM. It also
> implements the setend instruction, and loading of BE binaries even in
> LE emulation mode.
>
> Based on Paolo's original work. I have moved all the BE32 related work
> to the back of the series. Multiple parties are interested in the BE8
> work just on its own, so that could potentially be merged w/o BE32.
> PMM requested BE32 be at least thought out architecturally, so this
> series sees BE32 functionality through.
>
> I have tested all of LE. BE8 and BE32 in both linux-user mode (for
> regressions) and system mode (BE8 and BE32 are new here).
> My test application is here, the README gives some example command
> lines you can run:
>
> https://github.com/pcrost/arm-be-test
>
> Regards,
> Peter

It would be nice to get at least the emulation for 'setend' into the
next version, because it is needed for the Raspberry Pi emulation.

Peter C., are you planning a new pull request? Maybe the number
of commits needed can be reduced by adding the already reviewed
ones to QEMU.

Regards,
Stefan



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support
  2016-03-01  5:27 ` Stefan Weil
@ 2016-03-01 18:26   ` Peter Crosthwaite
  2016-03-01 18:43   ` Peter Crosthwaite
  1 sibling, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-03-01 18:26 UTC (permalink / raw)
  To: Stefan Weil
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers, Andrew Baumann,
	Alistair Francis, sridhar kulkarni, qemu-arm, Paolo Bonzini,
	Dmitry Osipenko, Piotr Król

On Mon, Feb 29, 2016 at 9:27 PM, Stefan Weil <sw@weilnetz.de> wrote:
> Am 18.01.2016 um 08:12 schrieb Peter Crosthwaite:
>> Hi All,
>>
>> This patch series adds system-mode big-endian support for ARM. It also
>> implements the setend instruction, and loading of BE binaries even in
>> LE emulation mode.
>>
>> Based on Paolo's original work. I have moved all the BE32 related work
>> to the back of the series. Multiple parties are interested in the BE8
>> work just on its own, so that could potentially be merged w/o BE32.
>> PMM requested BE32 be at least thought out architecturally, so this
>> series sees BE32 functionality through.
>>
>> I have tested all of LE. BE8 and BE32 in both linux-user mode (for
>> regressions) and system mode (BE8 and BE32 are new here).
>> My test application is here, the README gives some example command
>> lines you can run:
>>
>> https://github.com/pcrost/arm-be-test
>>
>> Regards,
>> Peter
>
> It would be nice to get at least the emulation for 'setend' into the
> next version, because it is needed for the Raspberry Pi emulation.
>
> Peter C., are you planning a new pull request? Maybe the number
> of commits needed can be reduced by adding the already reviewed
> ones to QEMU.
>

I have the respun branch based on Peter's comments tested as working.
I automated my tests so the last thing to do is bisect-ability test it
(test every commit for regressions) before I post it. I am stretched
and still have a series to review at the front of my todo list though.

Regards,
Peter

> Regards,
> Stefan
>
>

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

* Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support
  2016-03-01  5:27 ` Stefan Weil
  2016-03-01 18:26   ` Peter Crosthwaite
@ 2016-03-01 18:43   ` Peter Crosthwaite
  2016-03-01 21:03     ` Paolo Bonzini
  2016-03-01 21:34     ` Andrew Baumann
  1 sibling, 2 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-03-01 18:43 UTC (permalink / raw)
  To: Stefan Weil
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers, Andrew Baumann,
	Alistair Francis, sridhar kulkarni, qemu-arm, Paolo Bonzini,
	Piotr Król

On Mon, Feb 29, 2016 at 9:27 PM, Stefan Weil <sw@weilnetz.de> wrote:
> Am 18.01.2016 um 08:12 schrieb Peter Crosthwaite:
>> Hi All,
>>
>> This patch series adds system-mode big-endian support for ARM. It also
>> implements the setend instruction, and loading of BE binaries even in
>> LE emulation mode.
>>
>> Based on Paolo's original work. I have moved all the BE32 related work
>> to the back of the series. Multiple parties are interested in the BE8
>> work just on its own, so that could potentially be merged w/o BE32.
>> PMM requested BE32 be at least thought out architecturally, so this
>> series sees BE32 functionality through.
>>
>> I have tested all of LE. BE8 and BE32 in both linux-user mode (for
>> regressions) and system mode (BE8 and BE32 are new here).
>> My test application is here, the README gives some example command
>> lines you can run:
>>
>> https://github.com/pcrost/arm-be-test
>>
>> Regards,
>> Peter
>
> It would be nice to get at least the emulation for 'setend' into the
> next version, because it is needed for the Raspberry Pi emulation.
>

BTW if you can link me binaries and a failing command line for the
failing rPI work I can test it, I am currently doing my own standalone
tests (of linux user as well).

Regards,
Peter

> Peter C., are you planning a new pull request? Maybe the number
> of commits needed can be reduced by adding the already reviewed
> ones to QEMU.
>
> Regards,
> Stefan
>
>

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

* Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support
  2016-03-01 18:43   ` Peter Crosthwaite
@ 2016-03-01 21:03     ` Paolo Bonzini
  2016-03-01 21:34     ` Andrew Baumann
  1 sibling, 0 replies; 51+ messages in thread
From: Paolo Bonzini @ 2016-03-01 21:03 UTC (permalink / raw)
  To: Peter Crosthwaite, Stefan Weil
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers, Andrew Baumann,
	Alistair Francis, sridhar kulkarni, qemu-arm, Piotr Król

On 01/03/2016 19:43, Peter Crosthwaite wrote:
> On Mon, Feb 29, 2016 at 9:27 PM, Stefan Weil <sw@weilnetz.de> wrote:
>> It would be nice to get at least the emulation for 'setend' into the
>> next version, because it is needed for the Raspberry Pi emulation.
> 
> BTW if you can link me binaries and a failing command line for the
> failing rPI work I can test it, I am currently doing my own standalone
> tests (of linux user as well).

Try the repository at https://github.com/bavison/arm-mem.  IIRC you have
to change the "#if 0" in test.c to "#if 1".

Paolo

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

* Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support
  2016-03-01 18:43   ` Peter Crosthwaite
  2016-03-01 21:03     ` Paolo Bonzini
@ 2016-03-01 21:34     ` Andrew Baumann
  2016-03-02  5:31       ` Peter Crosthwaite
  1 sibling, 1 reply; 51+ messages in thread
From: Andrew Baumann @ 2016-03-01 21:34 UTC (permalink / raw)
  To: Peter Crosthwaite, Stefan Weil
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers,
	Alistair Francis, sridhar kulkarni, qemu-arm, Paolo Bonzini,
	Piotr Król

> From: Peter Crosthwaite [mailto:crosthwaitepeter@gmail.com]
> Sent: Tuesday, 1 March 2016 10:44 AM
> 
> On Mon, Feb 29, 2016 at 9:27 PM, Stefan Weil <sw@weilnetz.de> wrote:
> > Am 18.01.2016 um 08:12 schrieb Peter Crosthwaite:
> >> Hi All,
> >>
> >> This patch series adds system-mode big-endian support for ARM. It also
> >> implements the setend instruction, and loading of BE binaries even in
> >> LE emulation mode.
> >>
> >> Based on Paolo's original work. I have moved all the BE32 related work
> >> to the back of the series. Multiple parties are interested in the BE8
> >> work just on its own, so that could potentially be merged w/o BE32.
> >> PMM requested BE32 be at least thought out architecturally, so this
> >> series sees BE32 functionality through.
> >>
> >> I have tested all of LE. BE8 and BE32 in both linux-user mode (for
> >> regressions) and system mode (BE8 and BE32 are new here).
> >> My test application is here, the README gives some example command
> >> lines you can run:
> >>
> >> https://github.com/pcrost/arm-be-test
> >>
> >> Regards,
> >> Peter
> >
> > It would be nice to get at least the emulation for 'setend' into the
> > next version, because it is needed for the Raspberry Pi emulation.
> >
> 
> BTW if you can link me binaries and a failing command line for the
> failing rPI work I can test it, I am currently doing my own standalone
> tests (of linux user as well).

Download and unzip:
https://downloads.raspberrypi.org/raspbian_lite_latest

Then, mount the boot partition, and grab a copy of kernel7.img. You should now be able to boot on a current qemu with:

qemu-system-arm -M raspi2 -kernel kernel7.img -sd 2016-02-26-raspbian-jessie-lite.img -append "rw earlyprintk loglevel=8 console=ttyAMA0 root=/dev/mmcblk0p2 rootwait" -serial stdio -d unimp

At present, this fails with:

[   10.535232] VFS: Mounted root (ext4 filesystem) on device 179:2.
[   10.729685] devtmpfs: mounted
[   10.805125] Freeing unused kernel memory: 416K (80776000 - 807de000)
[   17.317286] random: systemd urandom read with 6 bits of entropy available
arm: unimplemented setend
[   17.366656] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
[   17.366656]
[   17.384625] CPU: 0 PID: 1 Comm: systemd Not tainted 4.1.7-v7+ #817
[   17.395562] Hardware name: BCM2709
[   17.404738] [<80018440>] (unwind_backtrace) from [<80013e0c>] (show_stack+0x20/0x24)
[   17.419042] [<80013e0c>] (show_stack) from [<80558548>] (dump_stack+0x98/0xe0)
[   17.432237] [<80558548>] (dump_stack) from [<8055473c>] (panic+0xa4/0x204)
[   17.444761] [<8055473c>] (panic) from [<8002937c>] (do_exit+0xa0c/0xa64)
[   17.452507] [<8002937c>] (do_exit) from [<80029470>] (do_group_exit+0x50/0xcc)
[   17.462827] [<80029470>] (do_group_exit) from [<80033ed4>] (get_signal+0x2b0/0x6e0)
[   17.474429] [<80033ed4>] (get_signal) from [<80013194>] (do_signal+0x98/0x3ac)
[   17.482176] [<80013194>] (do_signal) from [<80013690>] (do_work_pending+0xb8/0xc8)
[   17.490129] [<80013690>] (do_work_pending) from [<8000f9e4>] (work_pending+0xc/0x20)
[   17.501020] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
[   17.501020]

Cheers,
Andrew

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

* Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support
  2016-03-01 21:34     ` Andrew Baumann
@ 2016-03-02  5:31       ` Peter Crosthwaite
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2016-03-02  5:31 UTC (permalink / raw)
  To: Andrew Baumann
  Cc: Peter Maydell, Stefan Weil, qemu-devel@nongnu.org Developers,
	Alistair Francis, sridhar kulkarni, qemu-arm, Paolo Bonzini,
	Piotr Król

On Tue, Mar 1, 2016 at 1:34 PM, Andrew Baumann
<Andrew.Baumann@microsoft.com> wrote:
>> From: Peter Crosthwaite [mailto:crosthwaitepeter@gmail.com]
>> Sent: Tuesday, 1 March 2016 10:44 AM
>>
>> On Mon, Feb 29, 2016 at 9:27 PM, Stefan Weil <sw@weilnetz.de> wrote:
>> > Am 18.01.2016 um 08:12 schrieb Peter Crosthwaite:
>> >> Hi All,
>> >>
>> >> This patch series adds system-mode big-endian support for ARM. It also
>> >> implements the setend instruction, and loading of BE binaries even in
>> >> LE emulation mode.
>> >>
>> >> Based on Paolo's original work. I have moved all the BE32 related work
>> >> to the back of the series. Multiple parties are interested in the BE8
>> >> work just on its own, so that could potentially be merged w/o BE32.
>> >> PMM requested BE32 be at least thought out architecturally, so this
>> >> series sees BE32 functionality through.
>> >>
>> >> I have tested all of LE. BE8 and BE32 in both linux-user mode (for
>> >> regressions) and system mode (BE8 and BE32 are new here).
>> >> My test application is here, the README gives some example command
>> >> lines you can run:
>> >>
>> >> https://github.com/pcrost/arm-be-test
>> >>
>> >> Regards,
>> >> Peter
>> >
>> > It would be nice to get at least the emulation for 'setend' into the
>> > next version, because it is needed for the Raspberry Pi emulation.
>> >
>>
>> BTW if you can link me binaries and a failing command line for the
>> failing rPI work I can test it, I am currently doing my own standalone
>> tests (of linux user as well).
>
> Download and unzip:
> https://downloads.raspberrypi.org/raspbian_lite_latest
>
> Then, mount the boot partition, and grab a copy of kernel7.img. You should now be able to boot on a current qemu with:
>
> qemu-system-arm -M raspi2 -kernel kernel7.img -sd 2016-02-26-raspbian-jessie-lite.img -append "rw earlyprintk loglevel=8 console=ttyAMA0 root=/dev/mmcblk0p2 rootwait" -serial stdio -d unimp
>
> At present, this fails with:
>
> [   10.535232] VFS: Mounted root (ext4 filesystem) on device 179:2.
> [   10.729685] devtmpfs: mounted
> [   10.805125] Freeing unused kernel memory: 416K (80776000 - 807de000)
> [   17.317286] random: systemd urandom read with 6 bits of entropy available
> arm: unimplemented setend
> [   17.366656] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
> [   17.366656]
> [   17.384625] CPU: 0 PID: 1 Comm: systemd Not tainted 4.1.7-v7+ #817
> [   17.395562] Hardware name: BCM2709
> [   17.404738] [<80018440>] (unwind_backtrace) from [<80013e0c>] (show_stack+0x20/0x24)
> [   17.419042] [<80013e0c>] (show_stack) from [<80558548>] (dump_stack+0x98/0xe0)
> [   17.432237] [<80558548>] (dump_stack) from [<8055473c>] (panic+0xa4/0x204)
> [   17.444761] [<8055473c>] (panic) from [<8002937c>] (do_exit+0xa0c/0xa64)
> [   17.452507] [<8002937c>] (do_exit) from [<80029470>] (do_group_exit+0x50/0xcc)
> [   17.462827] [<80029470>] (do_group_exit) from [<80033ed4>] (get_signal+0x2b0/0x6e0)
> [   17.474429] [<80033ed4>] (get_signal) from [<80013194>] (do_signal+0x98/0x3ac)
> [   17.482176] [<80013194>] (do_signal) from [<80013690>] (do_work_pending+0xb8/0xc8)
> [   17.490129] [<80013690>] (do_work_pending) from [<8000f9e4>] (work_pending+0xc/0x20)
> [   17.501020] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
> [   17.501020]
>

Reproduced. With my patch series I am now getting further:

[    5.570600] VFS: Mounted root (ext4 filesystem) on device 179:2.
[    5.628967] devtmpfs: mounted
[    5.667292] Freeing unused kernel memory: 448K (8078a000 - 807fa000)
[    7.829100] random: systemd urandom read with 2 bits of entropy available
[    7.902604] systemd[1]: systemd 215 running in system mode. (+PAM
+AUDIT +SELINUX +IMA +SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ
-SECCOMP -APPARMOR)
[    7.913866] systemd[1]: Detected architecture 'arm'.

Welcome to Raspbian GNU/Linux 8 (jessie)!

[    8.625874] NET: Registered protocol family 10
[    8.645330] systemd[1]: Inserted module 'ipv6'
[    8.671989] systemd[1]: Set hostname to <raspberrypi>.
[   12.670915] systemd[1]: Cannot add dependency job for unit
display-manager.service, ignoring: Unit display-manager.service failed
to load: No such file or directory.
[   12.720439] systemd[1]: Starting Forward Password Requests to Wall
Directory Watch.
[   12.731310] systemd[1]: Started Forward Password Requests to Wall
Directory Watch.
[   12.734406] systemd[1]: Expecting device dev-ttyAMA0.device...
         Expecting device dev-ttyAMA0.device...

...

[  OK  ] Started Permit User Sessions.
[  OK  ] Started Login Service.
[  OK  ] Started System Logging Service.
[  OK  ] Started LSB: Apply config from /boot/os_config.json.
[  OK  ] Started dhcpcd on all interfaces.
[  OK  ] Reached target Network.
         Starting /etc/rc.local Compatibility...
[  OK  ] Reached target Network is Online.
         Starting LSB: Start NTP daemon...
[  OK  ] Started /etc/rc.local Compatibility.
         Starting Wait for Plymouth Boot Screen to Quit...
         Starting Terminate Plymouth Boot Screen...
[  OK  ] Started Wait for Plymouth Boot Screen to Quit.
         Starting Getty on tty1...
[  OK  ] Started Getty on tty1.
         Starting Serial Getty on ttyAMA0...
[  OK  ] Started Serial Getty on ttyAMA0.
[  OK  ] Reached target Login Prompts.
[  OK  ] Started Terminate Plymouth Boot Screen.

Raspbian GNU/Linux 8 raspberrypi ttyAMA0

raspberrypi login: pi
Password:
Linux raspberrypi 4.1.18-v7+ #846 SMP Thu Feb 25 14:22:53 GMT 2016 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
pi@raspberrypi:~$ cat /proc/cpuinfo
processor    : 0
model name    : ARMv7 Processor rev 1 (v7l)
BogoMIPS    : 38.40
Features    : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva
idivt vfpd32 lpae evtstrm
CPU implementer    : 0x41
CPU architecture: 7
CPU variant    : 0x2
CPU part    : 0xc0f
CPU revision    : 1

Hardware    : BCM2709
Revision    : 0000
Serial        : 0000000000000000
pi@raspberrypi:~$ uname -a
Linux raspberrypi 4.1.18-v7+ #846 SMP Thu Feb 25 14:22:53 GMT 2016
armv7l GNU/Linux

Regards,
Peter

> Cheers,
> Andrew

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

end of thread, other threads:[~2016-03-02  5:31 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-18  7:12 [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Crosthwaite
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 01/17] linux-user: arm: fix coding style for some linux-user signal functions Peter Crosthwaite
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 02/17] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode Peter Crosthwaite
2016-01-19 16:22   ` Peter Maydell
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 03/17] linux-user: arm: handle CPSR.E correctly in strex emulation Peter Crosthwaite
2016-01-19 16:24   ` Peter Maydell
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 04/17] target-arm: implement SCTLR.EE Peter Crosthwaite
2016-01-19 15:58   ` Peter Maydell
2016-02-27 21:56     ` Peter Crosthwaite
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 05/17] target-arm: pass DisasContext to gen_aa32_ld*/st* Peter Crosthwaite
2016-01-19 16:08   ` Peter Maydell
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 06/17] target-arm: introduce disas flag for endianness Peter Crosthwaite
2016-01-19 16:08   ` Peter Maydell
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 07/17] target-arm: a64: Add endianness support Peter Crosthwaite
2016-01-19 16:09   ` Peter Maydell
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header Peter Crosthwaite
2016-01-18 21:52   ` Alistair Francis
2016-01-19 16:11   ` Peter Maydell
2016-02-27 22:02     ` Peter Crosthwaite
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 09/17] target-arm: introduce tbflag for endianness Peter Crosthwaite
2016-01-19 16:15   ` Peter Maydell
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 10/17] target-arm: implement setend Peter Crosthwaite
2016-01-19 16:29   ` Peter Maydell
2016-02-27 22:14     ` Peter Crosthwaite
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 11/17] linux-user: arm: pass env to get_user_code_* Peter Crosthwaite
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 12/17] target-arm: implement SCTLR.B, drop bswap_code Peter Crosthwaite
2016-01-19 17:21   ` Peter Maydell
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 13/17] arm: linux-user: don't set CPSR.E in BE32 mode Peter Crosthwaite
2016-01-19 17:26   ` Peter Maydell
2016-01-19 17:35     ` Peter Maydell
2016-02-27 22:22       ` Peter Crosthwaite
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 14/17] target-arm: implement BE32 mode in system emulation Peter Crosthwaite
2016-01-19 17:39   ` Peter Maydell
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 15/17] loader: add API to load elf header Peter Crosthwaite
2016-01-19 17:50   ` Peter Maydell
2016-02-27 22:46     ` Peter Crosthwaite
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf Peter Crosthwaite
2016-01-19 17:53   ` Peter Maydell
2016-02-27 23:14     ` Peter Crosthwaite
2016-02-28 15:28       ` Peter Maydell
2016-02-28 20:16         ` Peter Crosthwaite
2016-01-18  7:12 ` [Qemu-devel] [PATCH v1 17/17] arm: boot: Support big-endian elfs Peter Crosthwaite
2016-01-19 18:06   ` Peter Maydell
2016-02-27 23:59     ` Peter Crosthwaite
2016-01-19 18:06 ` [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support Peter Maydell
2016-03-01  5:27 ` Stefan Weil
2016-03-01 18:26   ` Peter Crosthwaite
2016-03-01 18:43   ` Peter Crosthwaite
2016-03-01 21:03     ` Paolo Bonzini
2016-03-01 21:34     ` Andrew Baumann
2016-03-02  5:31       ` Peter Crosthwaite

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.