]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Support for executing 32 bit SPARC32PLUS files for Sparc64 user emulator
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 9 Oct 2007 16:34:29 +0000 (16:34 +0000)
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 9 Oct 2007 16:34:29 +0000 (16:34 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3378 c046a42c-6fe2-441c-8c8c-71466251a162

Changelog
Makefile.target
configure
linux-user/elfload.c
linux-user/elfload32.c [new file with mode: 0755]
linux-user/linuxload.c
linux-user/main.c
linux-user/qemu.h
linux-user/sparc64/syscall_nr.h

index 26fc301f2e784edb8d4e77d75af183c98a31033c..4c7a1215c8497c3941c4330153e56f423b0d00af 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -13,6 +13,7 @@
   - Read-only support for Parallels disk images (Alex Beregszaszi)
   - SVM (x86 virtualization) support (Alexander Graf)
   - CRIS emulation (Edgar E. Iglesias)
+  - SPARC32PLUS execution support (Blue Swirl)
 
 version 0.9.0:
 
index fe0cf372a2269a0978719a7ebb4c016d9313523d..8ebe3c3c757f41b3499673128b3ba2c178f6a74c 100644 (file)
@@ -254,6 +254,10 @@ LIBS+= $(AIOLIBS)
 ifdef TARGET_HAS_BFLT
 OBJS+= flatload.o
 endif
+ifdef TARGET_HAS_ELFLOAD32
+OBJS+= elfload32.o
+elfload32.o: elfload.c
+endif
 
 ifeq ($(TARGET_ARCH), i386)
 OBJS+= vm86.o
index a8dbf85114aba089f7aebbc3f252b4233fe2386f..8e705e1b043e4276d161150467a5575a367e7473 100755 (executable)
--- a/configure
+++ b/configure
@@ -999,6 +999,7 @@ echo "include ../config-host.mak" >> $config_mak
 echo "#include \"../config-host.h\"" >> $config_h
 
 bflt="no"
+elfload32="no"
 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
 echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
 
@@ -1023,6 +1024,7 @@ elif test "$target_cpu" = "sparc64" ; then
   echo "#define TARGET_ARCH \"sparc64\"" >> $config_h
   echo "#define TARGET_SPARC 1" >> $config_h
   echo "#define TARGET_SPARC64 1" >> $config_h
+  elfload32="yes"
 elif test "$target_cpu" = "ppc" ; then
   echo "TARGET_ARCH=ppc" >> $config_mak
   echo "#define TARGET_ARCH \"ppc\"" >> $config_h
@@ -1112,6 +1114,11 @@ if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
   echo "TARGET_HAS_BFLT=yes" >> $config_mak
   echo "#define TARGET_HAS_BFLT 1" >> $config_h
 fi
+# 32 bit ELF loader in addition to native 64 bit loader?
+if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then
+  echo "TARGET_HAS_ELFLOAD32=yes" >> $config_mak
+  echo "#define TARGET_HAS_ELFLOAD32 1" >> $config_h
+fi
 # sdl defines
 
 if test "$target_user_only" = "no"; then
index 1db6bab5e8a9ff0e7d09b35455b0b08d0ed79351..fbe7ddd8483c57f53bc4e163db2366fed76b5f9a 100644 (file)
 #include "qemu.h"
 #include "disas.h"
 
+/* from personality.h */
+
+/*
+ * Flags for bug emulation.
+ *
+ * These occupy the top three bytes.
+ */
+enum {
+       ADDR_NO_RANDOMIZE =     0x0040000,      /* disable randomization of VA space */
+       FDPIC_FUNCPTRS =        0x0080000,      /* userspace function ptrs point to descriptors
+                                                * (signal handling)
+                                                */
+       MMAP_PAGE_ZERO =        0x0100000,
+       ADDR_COMPAT_LAYOUT =    0x0200000,
+       READ_IMPLIES_EXEC =     0x0400000,
+       ADDR_LIMIT_32BIT =      0x0800000,
+       SHORT_INODE =           0x1000000,
+       WHOLE_SECONDS =         0x2000000,
+       STICKY_TIMEOUTS =       0x4000000,
+       ADDR_LIMIT_3GB =        0x8000000,
+};
+
+/*
+ * Personality types.
+ *
+ * These go in the low byte.  Avoid using the top bit, it will
+ * conflict with error returns.
+ */
+enum {
+       PER_LINUX =             0x0000,
+       PER_LINUX_32BIT =       0x0000 | ADDR_LIMIT_32BIT,
+       PER_LINUX_FDPIC =       0x0000 | FDPIC_FUNCPTRS,
+       PER_SVR4 =              0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+       PER_SVR3 =              0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
+       PER_SCOSVR3 =           0x0003 | STICKY_TIMEOUTS |
+                                        WHOLE_SECONDS | SHORT_INODE,
+       PER_OSR5 =              0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
+       PER_WYSEV386 =          0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
+       PER_ISCR4 =             0x0005 | STICKY_TIMEOUTS,
+       PER_BSD =               0x0006,
+       PER_SUNOS =             0x0006 | STICKY_TIMEOUTS,
+       PER_XENIX =             0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
+       PER_LINUX32 =           0x0008,
+       PER_LINUX32_3GB =       0x0008 | ADDR_LIMIT_3GB,
+       PER_IRIX32 =            0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
+       PER_IRIXN32 =           0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
+       PER_IRIX64 =            0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
+       PER_RISCOS =            0x000c,
+       PER_SOLARIS =           0x000d | STICKY_TIMEOUTS,
+       PER_UW7 =               0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+       PER_OSF4 =              0x000f,                  /* OSF/1 v4 */
+       PER_HPUX =              0x0010,
+       PER_MASK =              0x00ff,
+};
+
+/*
+ * Return the base personality without flags.
+ */
+#define personality(pers)      (pers & PER_MASK)
+
 /* this flag is uneffective under linux too, should be deleted */
 #ifndef MAP_DENYWRITE
 #define MAP_DENYWRITE 0
@@ -154,7 +214,7 @@ enum
 
 #define ELF_START_MMAP 0x80000000
 
-#define elf_check_arch(x) ( (x) == EM_SPARCV9 )
+#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
 
 #define ELF_CLASS   ELFCLASS64
 #define ELF_DATA    ELFDATA2MSB
@@ -168,7 +228,10 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
     regs->pc = infop->entry;
     regs->npc = regs->pc + 4;
     regs->y = 0;
-    regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
+    if (personality(infop->personality) == PER_LINUX32)
+        regs->u_regs[14] = infop->start_stack - 16 * 4;
+    else
+        regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
 }
 
 #else
@@ -412,6 +475,13 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 #define ELF_HWCAP 0
 #endif
 
+#ifdef OVERRIDE_ELF_CLASS
+#undef ELF_CLASS
+#define ELF_CLASS OVERRIDE_ELF_CLASS
+#undef bswaptls
+#define bswaptls(ptr) bswap32s(ptr)
+#endif
+
 #include "elf.h"
 
 struct exec
@@ -439,25 +509,6 @@ struct exec
 /* max code+data+bss+brk space allocated to ET_DYN executables */
 #define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
 
-/* from personality.h */
-
-/* Flags for bug emulation. These occupy the top three bytes. */
-#define STICKY_TIMEOUTS                0x4000000
-#define WHOLE_SECONDS          0x2000000
-
-/* Personality types. These go in the low byte. Avoid using the top bit,
- * it will conflict with error returns.
- */
-#define PER_MASK               (0x00ff)
-#define PER_LINUX              (0x0000)
-#define PER_SVR4               (0x0001 | STICKY_TIMEOUTS)
-#define PER_SVR3               (0x0002 | STICKY_TIMEOUTS)
-#define PER_SCOSVR3            (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS)
-#define PER_WYSEV386           (0x0004 | STICKY_TIMEOUTS)
-#define PER_ISCR4              (0x0005 | STICKY_TIMEOUTS)
-#define PER_BSD                        (0x0006)
-#define PER_XENIX              (0x0007 | STICKY_TIMEOUTS)
-
 /* Necessary parameters */
 #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
@@ -587,8 +638,8 @@ static target_ulong copy_elf_strings(int argc,char ** argv, void **page,
     return p;
 }
 
-target_ulong setup_arg_pages(target_ulong p, struct linux_binprm * bprm,
-                             struct image_info * info)
+static target_ulong setup_arg_pages(target_ulong p, struct linux_binprm *bprm,
+                                    struct image_info *info)
 {
     target_ulong stack_base, size, error;
     int i;
diff --git a/linux-user/elfload32.c b/linux-user/elfload32.c
new file mode 100755 (executable)
index 0000000..d1a15ff
--- /dev/null
@@ -0,0 +1,30 @@
+#define OVERRIDE_ELF_CLASS ELFCLASS32
+#define load_elf_binary load_elf_binary32
+#define do_init_thread do_init_thread32
+
+#include "elfload.c"
+
+#undef load_elf_binary
+#undef do_init_thread
+
+int load_elf_binary(struct linux_binprm *bprm, struct target_pt_regs *regs,
+                    struct image_info *info);
+
+int load_elf_binary_multi(struct linux_binprm *bprm,
+                          struct target_pt_regs *regs,
+                          struct image_info *info)
+{
+    struct elfhdr *elf_ex;
+    int retval;
+
+    elf_ex = (struct elfhdr *) bprm->buf;          /* exec-header */
+    if (elf_ex->e_ident[EI_CLASS] == ELFCLASS64) {
+        retval = load_elf_binary(bprm, regs, info);
+    } else {
+        retval = load_elf_binary32(bprm, regs, info);
+        if (personality(info->personality) == PER_LINUX)
+            info->personality = PER_LINUX32;
+    }
+
+    return retval;
+}
index 0efbb76ce4a52799ea1a9d4592608061388d525f..51f29531caa3cd48e746b6cecc46181c81a85a9d 100644 (file)
@@ -169,7 +169,11 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
                 && bprm.buf[1] == 'E'
                 && bprm.buf[2] == 'L'
                 && bprm.buf[3] == 'F') {
+#ifndef TARGET_HAS_ELFLOAD32
             retval = load_elf_binary(&bprm,regs,infop);
+#else
+            retval = load_elf_binary_multi(&bprm, regs, infop);
+#endif
 #if defined(TARGET_HAS_BFLT)
         } else if (bprm.buf[0] == 'b'
                 && bprm.buf[1] == 'F'
index b4bc93da5f3e9b0083e2582a357ce62960718db7..7de7ff5a717a8e17705a15e9cea7f3984bd4c922 100644 (file)
@@ -564,6 +564,7 @@ void cpu_loop (CPUSPARCState *env)
         case 0x88:
         case 0x90:
 #else
+        case 0x110:
         case 0x16d:
 #endif
             ret = do_syscall (env, env->gregs[1],
index 2c48e92311c07692110e57387e7eaf5a87b202b0..8a7cb2479a52d53900ed0df76a1008195ba4d85a 100644 (file)
@@ -124,6 +124,11 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info);
 int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info);
+#ifdef TARGET_HAS_ELFLOAD32
+int load_elf_binary_multi(struct linux_binprm *bprm,
+                          struct target_pt_regs *regs,
+                          struct image_info *info);
+#endif
 
 void memcpy_to_target(target_ulong dest, const void *src,
                       unsigned long len);
index 53102945a064e02f74569efd1493b08a1df0907d..70bee8080c2c44560def7ca2bcd573cd03dad480 100644 (file)
 #define TARGET_NR_sigaltstack   28 /* Common                                      */
 #define TARGET_NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
 #define TARGET_NR_utime               30 /* Implemented via utimes() under SunOS        */
-/* #define TARGET_NR_lchown32         31    Linux sparc32 specific                      */
-/* #define TARGET_NR_fchown32         32    Linux sparc32 specific                      */
+#define TARGET_NR_lchown32            31 /* Linux sparc32 specific                      */
+#define TARGET_NR_fchown32            32 /* Linux sparc32 specific                      */
 #define TARGET_NR_access              33 /* Common                                      */
 #define TARGET_NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
-/* #define TARGET_NR_chown32          35    Linux sparc32 specific                      */
+#define TARGET_NR_chown32             35 /*  Linux sparc32 specific                     */
 #define TARGET_NR_sync                36 /* Common                                      */
 #define TARGET_NR_kill                37 /* Common                                      */
 #define TARGET_NR_stat                38 /* Common                                      */
@@ -42,7 +42,7 @@
 #define TARGET_NR_dup                 41 /* Common                                      */
 #define TARGET_NR_pipe                42 /* Common                                      */
 #define TARGET_NR_times               43 /* Implemented via getrusage() in SunOS        */
-/* #define TARGET_NR_getuid32         44    Linux sparc32 specific                      */
+#define TARGET_NR_getuid32            44 /* Linux sparc32 specific                      */
 #define TARGET_NR_umount2             45 /* Linux Specific                              */
 #define TARGET_NR_setgid              46 /* Implemented via setregid() in SunOS         */
 #define TARGET_NR_getgid              47 /* Common                                      */
 #define TARGET_NR_getegid             50 /* SunOS calls getgid()                        */
 #define TARGET_NR_acct                51 /* Common                                      */
 #define TARGET_NR_memory_ordering       52 /* Linux Specific                              */
-/* #define TARGET_NR_getgid32         53    Linux sparc32 specific                      */
+#define TARGET_NR_getgid32            53 /* Linux sparc32 specific                      */
 #define TARGET_NR_ioctl               54 /* Common                                      */
 #define TARGET_NR_reboot              55 /* Common                                      */
-/* #define TARGET_NR_mmap2              56    Linux sparc32 Specific                      */
+#define TARGET_NR_mmap2                      56 /* Linux sparc32 Specific                      */
 #define TARGET_NR_symlink             57 /* Common                                      */
 #define TARGET_NR_readlink            58 /* Common                                      */
 #define TARGET_NR_execve              59 /* Common                                      */
 #define TARGET_NR_umask               60 /* Common                                      */
 #define TARGET_NR_chroot              61 /* Common                                      */
 #define TARGET_NR_fstat               62 /* Common                                      */
-/* #define TARGET_NR_fstat64          63    Linux sparc32 Specific                      */
+#define TARGET_NR_fstat64             63 /* Linux sparc32 Specific                      */
 #define TARGET_NR_getpagesize         64 /* Common                                      */
 #define TARGET_NR_msync               65 /* Common in newer 1.3.x revs...               */
 #define TARGET_NR_vfork               66 /* Common                                      */
 #define TARGET_NR_pread64             67 /* Linux Specific                              */
 #define TARGET_NR_pwrite64            68 /* Linux Specific                              */
-/* #define TARGET_NR_geteuid32        69    Linux sparc32, sbrk under SunOS             */
-/* #define TARGET_NR_getegid32        70    Linux sparc32, sstk under SunOS             */
+#define TARGET_NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */
+#define TARGET_NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */
 #define TARGET_NR_mmap                71 /* Common                                      */
-/* #define TARGET_NR_setreuid32       72    Linux sparc32, vadvise under SunOS          */
+#define TARGET_NR_setreuid32          72 /* Linux sparc32, vadvise under SunOS          */
 #define TARGET_NR_munmap              73 /* Common                                      */
 #define TARGET_NR_mprotect            74 /* Common                                      */
 #define TARGET_NR_madvise             75 /* Common                                      */
 #define TARGET_NR_vhangup             76 /* Common                                      */
-/* #define TARGET_NR_truncate64       77    Linux sparc32 Specific                        */
+#define TARGET_NR_truncate64          77 /* Linux sparc32 Specific                     */
 #define TARGET_NR_mincore             78 /* Common                                      */
 #define TARGET_NR_getgroups           79 /* Common                                      */
 #define TARGET_NR_setgroups           80 /* Common                                      */
 #define TARGET_NR_getpgrp             81 /* Common                                      */
-/* #define TARGET_NR_setgroups32      82    Linux sparc32, setpgrp under SunOS          */
+#define TARGET_NR_setgroups32         82 /* Linux sparc32, setpgrp under SunOS          */
 #define TARGET_NR_setitimer           83 /* Common                                      */
-/* #define TARGET_NR_ftruncate64      84    Linux sparc32 Specific                        */
+#define TARGET_NR_ftruncate64         84 /* Linux sparc32 Specific                      */
 #define TARGET_NR_swapon              85 /* Common                                      */
 #define TARGET_NR_getitimer           86 /* Common                                      */
-/* #define TARGET_NR_setuid32         87    Linux sparc32, gethostname under SunOS      */
+#define TARGET_NR_setuid32            87 /* Linux sparc32, gethostname under SunOS      */
 #define TARGET_NR_sethostname         88 /* Common                                      */
-/* #define TARGET_NR_setgid32         89    Linux sparc32, getdtablesize under SunOS    */
+#define TARGET_NR_setgid32            89 /* Linux sparc32, getdtablesize under SunOS    */
 #define TARGET_NR_dup2                90 /* Common                                      */
-/* #define TARGET_NR_setfsuid32       91    Linux sparc32, getdopt under SunOS          */
+#define TARGET_NR_setfsuid32          91 /* Linux sparc32, getdopt under SunOS          */
 #define TARGET_NR_fcntl               92 /* Common                                      */
 #define TARGET_NR_select              93 /* Common                                      */
-/* #define TARGET_NR_setfsgid32       94    Linux sparc32, setdopt under SunOS          */
+#define TARGET_NR_setfsgid32          94 /* Linux sparc32, setdopt under SunOS          */
 #define TARGET_NR_fsync               95 /* Common                                      */
 #define TARGET_NR_setpriority         96 /* Common                                      */
 #define TARGET_NR_socket              97 /* Common                                      */
 #define TARGET_NR_getresuid          109 /* Linux Specific, sigblock under SunOS          */
 #define TARGET_NR_setresgid          110 /* Linux Specific, sigsetmask under SunOS        */
 #define TARGET_NR_getresgid          111 /* Linux Specific, sigpause under SunOS          */
-/* #define TARGET_NR_setregid32       75    Linux sparc32, sigstack under SunOS         */
+/* #define TARGET_NR_setregid32          75  Linux sparc32, sigstack under SunOS         */
 #define TARGET_NR_recvmsg            113 /* Common                                      */
 #define TARGET_NR_sendmsg            114 /* Common                                      */
-/* #define TARGET_NR_getgroups32     115    Linux sparc32, vtrace under SunOS           */
+#define TARGET_NR_getgroups32        115 /* Linux sparc32, vtrace under SunOS           */
 #define TARGET_NR_gettimeofday       116 /* Common                                      */
 #define TARGET_NR_getrusage          117 /* Common                                      */
 #define TARGET_NR_getsockopt         118 /* Common                                      */
 #define TARGET_NR_truncate           129 /* Common                                      */
 #define TARGET_NR_ftruncate          130 /* Common                                      */
 #define TARGET_NR_flock              131 /* Common                                      */
-/* #define TARGET_NR_lstat64           132    Linux sparc32 Specific                      */
+#define TARGET_NR_lstat64           132 /* Linux sparc32 Specific                      */
 #define TARGET_NR_sendto             133 /* Common                                      */
 #define TARGET_NR_shutdown           134 /* Common                                      */
 #define TARGET_NR_socketpair         135 /* Common                                      */
 #define TARGET_NR_mkdir              136 /* Common                                      */
 #define TARGET_NR_rmdir              137 /* Common                                      */
 #define TARGET_NR_utimes             138 /* SunOS Specific                              */
-/* #define TARGET_NR_stat64            139    Linux sparc32 Specific                      */
+#define TARGET_NR_stat64            139 /* Linux sparc32 Specific                         */
 #define TARGET_NR_sendfile64         140 /* adjtime under SunOS                         */
 #define TARGET_NR_getpeername        141 /* Common                                      */
 #define TARGET_NR_futex              142 /* gethostid under SunOS                       */
 /* #define TARGET_NR_putmsg          152    SunOS Specific                              */
 #define TARGET_NR_poll               153 /* Common                                      */
 #define TARGET_NR_getdents64           154 /* Linux specific                              */
-/* #define TARGET_NR_fcntl64         155    Linux sparc32 Specific                      */
+#define TARGET_NR_fcntl64            155 /* Linux sparc32 Specific                      */
 /* #define TARGET_NR_getdirentries   156    SunOS Specific                              */
 #define TARGET_NR_statfs             157 /* Common                                      */
 #define TARGET_NR_fstatfs            158 /* Common                                      */
 #define TARGET_NR_setfsuid           228 /* Linux Specific                              */
 #define TARGET_NR_setfsgid           229 /* Linux Specific                              */
 #define TARGET_NR__newselect         230 /* Linux Specific                              */
-#ifdef __KERNEL__
-#define TARGET_NR_time         231 /* Linux sparc32                               */
-#endif
+#define TARGET_NR_time               231 /* Linux sparc32                               */
 /* #define TARGET_NR_oldstat         232    Linux Specific                              */
 #define TARGET_NR_stime              233 /* Linux Specific                              */
 #define TARGET_NR_statfs64           234 /* Linux Specific                              */