Index: configure =================================================================== RCS file: /sources/qemu/qemu/configure,v retrieving revision 1.161 diff -u -d -d -p -r1.161 configure --- configure 9 Oct 2007 16:34:28 -0000 1.161 +++ configure 10 Oct 2007 07:38:59 -0000 @@ -1029,11 +1030,12 @@ elif test "$target_cpu" = "ppc" ; then echo "TARGET_ARCH=ppc" >> $config_mak echo "#define TARGET_ARCH \"ppc\"" >> $config_h echo "#define TARGET_PPC 1" >> $config_h elif test "$target_cpu" = "ppc64" ; then echo "TARGET_ARCH=ppc64" >> $config_mak echo "#define TARGET_ARCH \"ppc64\"" >> $config_h echo "#define TARGET_PPC 1" >> $config_h echo "#define TARGET_PPC64 1" >> $config_h + elfload32="yes" elif test "$target_cpu" = "ppcemb" ; then echo "TARGET_ARCH=ppcemb" >> $config_mak echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h Index: linux-user/elfload.c =================================================================== RCS file: /sources/qemu/qemu/linux-user/elfload.c,v retrieving revision 1.51 diff -u -d -d -p -r1.51 elfload.c --- linux-user/elfload.c 9 Oct 2007 16:34:29 -0000 1.51 +++ linux-user/elfload.c 10 Oct 2007 07:38:59 -0000 @@ -12,65 +12,10 @@ #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) +#define personality(pers) ((pers) & PER_MASK) /* this flag is uneffective under linux too, should be deleted */ #ifndef MAP_DENYWRITE @@ -215,6 +160,7 @@ enum #define ELF_START_MMAP 0x80000000 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS ) +#define elf_check_arch32(x) ( (x) == EM_SPARC32PLUS ) #define ELF_CLASS ELFCLASS64 #define ELF_DATA ELFDATA2MSB @@ -261,7 +207,8 @@ static inline void init_thread(struct ta #ifdef TARGET_PPC64 -#define elf_check_arch(x) ( (x) == EM_PPC64 ) +#define elf_check_arch(x) ( (x) == EM_PPC64 || (x) == EM_PPC ) +#define elf_check_arch32(x) ( (x) == EM_PPC ) #define ELF_CLASS ELFCLASS64 @@ -311,32 +258,51 @@ do { NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ } while (0) -static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) +static inline void init_thread(struct target_pt_regs *_regs, + struct image_info *infop) { target_ulong pos = infop->start_stack; - target_ulong tmp; + target_ulong tmp, elen; #ifdef TARGET_PPC64 target_ulong entry, toc; #endif - _regs->msr = 1 << MSR_PR; /* Set user mode */ + _regs->msr = 1ULL << MSR_PR; /* Set user mode */ _regs->gpr[1] = infop->start_stack; #ifdef TARGET_PPC64 - entry = ldq_raw(infop->entry) + infop->load_addr; - toc = ldq_raw(infop->entry + 8) + infop->load_addr; - _regs->gpr[2] = toc; - infop->entry = entry; + if (personality(infop->personality) != PER_LINUX32) { + entry = ldq_raw(infop->entry) + infop->load_addr; + toc = ldq_raw(infop->entry + 8) + infop->load_addr; + _regs->gpr[2] = toc; + infop->entry = entry; + } #endif _regs->nip = infop->entry; /* Note that isn't exactly what regular kernel does * but this is what the ABI wants and is needed to allow * execution of PPC BSD programs. */ - _regs->gpr[3] = tgetl(pos); - pos += sizeof(target_ulong); +#ifdef TARGET_PPC64 + if (personality(infop->personality) != PER_LINUX32) { + _regs->msr = 1ULL << MSR_SF; /* Set 64 bits mode */ + _regs->gpr[3] = ldq(pos); + elen = sizeof(uint64_t); + } else +#endif + { + _regs->gpr[3] = ldl(pos); + elen = sizeof(uint32_t); + } + pos += elen; _regs->gpr[4] = pos; - for (tmp = 1; tmp != 0; pos += sizeof(target_ulong)) - tmp = ldl(pos); + for (tmp = 1; tmp != 0; pos += elen) { +#ifdef TARGET_PPC64 + if (personality(infop->personality) != PER_LINUX32) + tmp = ldq(pos); + else +#endif + tmp = ldl(pos); + } _regs->gpr[5] = pos; } @@ -742,8 +708,14 @@ static target_ulong create_elf_tables(ta int size; target_ulong u_platform; const char *k_platform; - const int n = sizeof(elf_addr_t); + int n; +#ifdef OVERRIDE_ELF_CLASS + if (personality(info->personality) == PER_LINUX32) + n = sizeof(uint32_t); + else +#endif + n = sizeof(elf_addr_t); sp = p; u_platform = 0; k_platform = ELF_PLATFORM; @@ -809,7 +781,7 @@ static target_ulong create_elf_tables(ta #endif #undef NEW_AUX_ENT - sp = loader_build_argptr(envc, argc, sp, p, !ibcs); + sp = loader_build_argptr(envc, argc, sp, p, !ibcs, n); return sp; } @@ -1388,7 +1359,12 @@ int load_elf_binary(struct linux_binprm load_symbols(&elf_ex, bprm->fd); if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); - info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); +#ifdef OVERRIDE_ELF_CLASS + if (elf_check_arch32(elf_ex.e_machine)) + info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX32); + else +#endif + info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); #ifdef LOW_ELF_STACK info->start_stack = bprm->p = elf_stack - 4; Index: linux-user/flatload.c =================================================================== RCS file: /sources/qemu/qemu/linux-user/flatload.c,v retrieving revision 1.7 diff -u -d -d -p -r1.7 flatload.c --- linux-user/flatload.c 17 Sep 2007 08:09:49 -0000 1.7 +++ linux-user/flatload.c 10 Oct 2007 07:38:59 -0000 @@ -766,7 +766,8 @@ int load_flt_binary(struct linux_binprm stack_len *= sizeof(target_ulong); if ((sp + stack_len) & 15) sp -= 16 - ((sp + stack_len) & 15); - sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1); + sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1, + sizeof(target_ulong)); /* Fake some return addresses to ensure the call chain will * initialise library in order for us. We are required to call Index: linux-user/linuxload.c =================================================================== RCS file: /sources/qemu/qemu/linux-user/linuxload.c,v retrieving revision 1.6 diff -u -d -d -p -r1.6 linuxload.c --- linux-user/linuxload.c 9 Oct 2007 16:34:29 -0000 1.6 +++ linux-user/linuxload.c 10 Oct 2007 07:38:59 -0000 @@ -109,10 +109,21 @@ static int prepare_binprm(struct linux_b } /* Construct the envp and argv tables on the target stack. */ +static inline void putl (target_ulong addr, target_ulong data, int n) +{ + if (n == sizeof(target_ulong)) { + tputl(addr, data); + } else { + /* Force 32 bits store for 32 program executed on a 64 bits target */ + stl(addr, data); + } +} + target_ulong loader_build_argptr(int envc, int argc, target_ulong sp, - target_ulong stringp, int push_ptr) + target_ulong stringp, int push_ptr, + int plen) { - int n = sizeof(target_ulong); + int n = plen; target_ulong envp; target_ulong argv; @@ -121,21 +132,21 @@ target_ulong loader_build_argptr(int env sp -= (argc + 1) * n; argv = sp; if (push_ptr) { - sp -= n; tputl(sp, envp); - sp -= n; tputl(sp, argv); + sp -= n; putl(sp, envp, n); + sp -= n; putl(sp, argv, n); } - sp -= n; tputl(sp, argc); + sp -= n; putl(sp, argc, n); while (argc-- > 0) { - tputl(argv, stringp); argv += n; + putl(argv, stringp, n); argv += n; stringp += target_strlen(stringp) + 1; } - tputl(argv, 0); + putl(argv, 0, n); while (envc-- > 0) { - tputl(envp, stringp); envp += n; + putl(envp, stringp, n); envp += n; stringp += target_strlen(stringp) + 1; } - tputl(envp, 0); + putl(envp, 0, n); return sp; } Index: linux-user/main.c =================================================================== RCS file: /sources/qemu/qemu/linux-user/main.c,v retrieving revision 1.131 diff -u -d -d -p -r1.131 main.c --- linux-user/main.c 9 Oct 2007 16:34:29 -0000 1.131 +++ linux-user/main.c 10 Oct 2007 07:38:59 -0000 @@ -2159,8 +2159,17 @@ int main(int argc, char **argv) int i; /* Choose and initialise CPU */ +#if defined(TARGET_PPC64) + if (cpu_model == NULL) { + if (get_personality(info) == PER_LINUX32) + cpu_model = "750"; + else + cpu_model = "970"; + } +#else if (cpu_model == NULL) cpu_model = "750"; +#endif ppc_find_by_name(cpu_model, &def); if (def == NULL) { cpu_abort(env, @@ -2172,9 +2181,6 @@ int main(int argc, char **argv) if (i != 12 && i != 6 && i != 13) env->msr[i] = (regs->msr >> i) & 1; } -#if defined(TARGET_PPC64) - msr_sf = 1; -#endif env->nip = regs->nip; for(i = 0; i < 32; i++) { env->gpr[i] = regs->gpr[i]; Index: linux-user/qemu.h =================================================================== RCS file: /sources/qemu/qemu/linux-user/qemu.h,v retrieving revision 1.40 diff -u -d -d -p -r1.40 qemu.h --- linux-user/qemu.h 9 Oct 2007 16:34:29 -0000 1.40 +++ linux-user/qemu.h 10 Oct 2007 07:38:59 -0000 @@ -16,6 +16,66 @@ * Basically, it replicates in user space what would be certain * task_struct fields in the kernel */ +/* 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 get_personality(infop) (((infop)->personality) & PER_MASK) + struct image_info { target_ulong load_addr; target_ulong start_code; @@ -116,7 +176,7 @@ struct linux_binprm { void do_init_thread(struct target_pt_regs *regs, struct image_info *infop); target_ulong loader_build_argptr(int envc, int argc, target_ulong sp, - target_ulong stringp, int push_ptr); + target_ulong stringp, int push_ptr, int plen); int loader_exec(const char * filename, char ** argv, char ** envp, struct target_pt_regs * regs, struct image_info *infop);