summary refs log tree commit diff stats
path: root/linux-user/main.c
diff options
context:
space:
mode:
authorBlue Swirl <blauwirbel@gmail.com>2012-04-07 11:45:25 +0000
committerBlue Swirl <blauwirbel@gmail.com>2012-04-07 11:45:25 +0000
commitadcd61f7fcd5a24e65b2ec087bfae2356805993b (patch)
treea74ea7fff914a0237e5190d5c97866bef1b3d21b /linux-user/main.c
parent6375e09e79964fa6eac3e8426d25c8b759185482 (diff)
parentd8fd2954996255ba6ad610917e7849832d0120b7 (diff)
downloadfocaccia-qemu-adcd61f7fcd5a24e65b2ec087bfae2356805993b.tar.gz
focaccia-qemu-adcd61f7fcd5a24e65b2ec087bfae2356805993b.zip
Merge branch 'linux-user-for-upstream' of git://git.linaro.org/people/rikuvoipio/qemu
* 'linux-user-for-upstream' of git://git.linaro.org/people/rikuvoipio/qemu:
  Userspace ARM BE8 support
  elf.h: Update EF_ARM_ constants to newer ABI versions
  arm-linux-user: fix elfload.c's AT_HWCAP to reflect cpu features.
  linux-user/arm/syscall_nr.h: Add syscall number for ppoll
  linux-user: Add support for prctl PR_GET_NAME and PR_SET_NAME
  linux-user/syscall.c: Fix indentation in prctl handling
  linux-user: reserve 4GB of vmem for 32-on-64
  linux-user: resolve reserved_va vma downwards
  linux-user: take RESERVED_VA into account for g2h_valid()
  linux-user: fix fallocate
  linux-user: Add ioctl for BLKBSZGET
  linux-user: add BLKSSZGET ioctl wrapper
  linux-user: fix BLK ioctl arguments
  linux-user: add struct old_dev_t compat
  linux-user: implement device mapper ioctls
  linux-user: target_argv is placed on ts->bprm->argv and can't be freed()
  linux-user: improve fake /proc/self/stat making `ps` not segfault.
Diffstat (limited to 'linux-user/main.c')
-rw-r--r--linux-user/main.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 962677e01d..191b75060d 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -33,6 +33,7 @@
 #include "tcg.h"
 #include "qemu-timer.h"
 #include "envlist.h"
+#include "elf.h"
 
 #define DEBUG_LOGFILE "/tmp/qemu.log"
 
@@ -48,8 +49,19 @@ unsigned long mmap_min_addr;
 #if defined(CONFIG_USE_GUEST_BASE)
 unsigned long guest_base;
 int have_guest_base;
+#if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64)
+/*
+ * When running 32-on-64 we should make sure we can fit all of the possible
+ * guest address space into a contiguous chunk of virtual host memory.
+ *
+ * This way we will never overlap with our own libraries or binaries or stack
+ * or anything else that QEMU maps.
+ */
+unsigned long reserved_va = 0xf7000000;
+#else
 unsigned long reserved_va;
 #endif
+#endif
 
 static void usage(void);
 
@@ -463,6 +475,22 @@ void cpu_loop(CPUX86State *env)
 
 #ifdef TARGET_ARM
 
+#define get_user_code_u32(x, gaddr, doswap)             \
+    ({ abi_long __r = get_user_u32((x), (gaddr));       \
+        if (!__r && (doswap)) {                         \
+            (x) = bswap32(x);                           \
+        }                                               \
+        __r;                                            \
+    })
+
+#define get_user_code_u16(x, gaddr, doswap)             \
+    ({ abi_long __r = get_user_u16((x), (gaddr));       \
+        if (!__r && (doswap)) {                         \
+            (x) = bswap16(x);                           \
+        }                                               \
+        __r;                                            \
+    })
+
 /*
  * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
  * Input:
@@ -696,7 +724,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_u32(opcode, env->regs[15]);
+                get_user_code_u32(opcode, env->regs[15], env->bswap_code);
 
                 rc = EmulateAll(opcode, &ts->fpa, env);
                 if (rc == 0) { /* illegal instruction */
@@ -766,23 +794,25 @@ void cpu_loop(CPUARMState *env)
                 if (trapnr == EXCP_BKPT) {
                     if (env->thumb) {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_u16(insn, env->regs[15]);
+                        get_user_code_u16(insn, env->regs[15], env->bswap_code);
                         n = insn & 0xff;
                         env->regs[15] += 2;
                     } else {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_u32(insn, env->regs[15]);
+                        get_user_code_u32(insn, env->regs[15], env->bswap_code);
                         n = (insn & 0xf) | ((insn >> 4) & 0xff0);
                         env->regs[15] += 4;
                     }
                 } else {
                     if (env->thumb) {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_u16(insn, env->regs[15] - 2);
+                        get_user_code_u16(insn, env->regs[15] - 2,
+                                          env->bswap_code);
                         n = insn & 0xff;
                     } else {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_u32(insn, env->regs[15] - 4);
+                        get_user_code_u32(insn, env->regs[15] - 4,
+                                          env->bswap_code);
                         n = insn & 0xffffff;
                     }
                 }
@@ -3420,6 +3450,7 @@ int main(int argc, char **argv, char **envp)
             guest_base = HOST_PAGE_ALIGN((unsigned long)p);
         }
         qemu_log("Reserved 0x%lx bytes of guest address space\n", reserved_va);
+        mmap_next_start = reserved_va;
     }
 
     if (reserved_va || have_guest_base) {
@@ -3486,11 +3517,6 @@ int main(int argc, char **argv, char **envp)
         _exit(1);
     }
 
-    for (i = 0; i < target_argc; i++) {
-        free(target_argv[i]);
-    }
-    free(target_argv);
-
     for (wrk = target_environ; *wrk; wrk++) {
         free(*wrk);
     }
@@ -3650,6 +3676,11 @@ int main(int argc, char **argv, char **envp)
         for(i = 0; i < 16; i++) {
             env->regs[i] = regs->uregs[i];
         }
+        /* Enable BE8.  */
+        if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
+            && (info->elf_flags & EF_ARM_BE8)) {
+            env->bswap_code = 1;
+        }
     }
 #elif defined(TARGET_UNICORE32)
     {