PowerPC target support (Jocelyn Mayer) - added better support for uid16
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 23 Nov 2003 17:05:30 +0000 (17:05 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 23 Nov 2003 17:05:30 +0000 (17:05 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@474 c046a42c-6fe2-441c-8c8c-71466251a162

Changelog
Makefile.target
configure
cpu-all.h
cpu-exec.c
disas.c
dyngen-exec.h
linux-user/elfload.c
linux-user/main.c
linux-user/syscall.c
linux-user/syscall_defs.h

index 3c98c5c..401f364 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -9,7 +9,8 @@ version 0.5.1:
   - IRET and INT fixes in VM86 mode with IOPL=3
   - Port I/Os use TSS io map
   - Full task switching/task gate support
-  - added verr, verw, arpl
+  - added verr, verw, arpl, fcmovxx
+  - PowerPC target support (Jocelyn Mayer)
 
 version 0.5.0:
   
index b888876..eb2e6db 100644 (file)
@@ -146,6 +146,10 @@ ifeq ($(TARGET_ARCH), i386)
 LIBOBJS+=helper.o helper2.o
 endif
 
+ifeq ($(TARGET_ARCH), ppc)
+LIBOBJS+=helper.o
+endif
+
 # NOTE: the disassembler code is only needed for debugging
 LIBOBJS+=disas.o 
 ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
index 3c9a298..05bc3b6 100755 (executable)
--- a/configure
+++ b/configure
@@ -27,7 +27,7 @@ ar="ar"
 make="make"
 strip="strip"
 cpu=`uname -m`
-target_list="i386-user i386 i386-softmmu arm-user sparc-user"
+target_list="i386-user i386 i386-softmmu arm-user sparc-user ppc-user"
 case "$cpu" in
   i386|i486|i586|i686|i86pc|BePC)
     cpu="i386"
@@ -322,6 +322,7 @@ config_h=$target_dir/config.h
 target_cpu=`echo $target | cut -d '-' -f 1`
 target_bigendian="no"
 [ "$target_cpu" = "sparc" ] && target_bigendian=yes
+[ "$target_cpu" = "ppc" ] && target_bigendian=yes
 target_softmmu="no"
 if expr $target : '.*-softmmu' > /dev/null ; then
   target_softmmu="yes"
@@ -358,6 +359,10 @@ elif test "$target_cpu" = "sparc" ; then
   echo "TARGET_ARCH=sparc" >> $config_mak
   echo "#define TARGET_ARCH \"sparc\"" >> $config_h
   echo "#define TARGET_SPARC 1" >> $config_h
+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
 else
   echo "Unsupported target CPU"
   exit 1
index c7491a0..9c88082 100644 (file)
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -395,6 +395,15 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
 #define cpu_interrupt cpu_sparc_interrupt
 #define cpu_signal_handler cpu_sparc_signal_handler
 
+#elif defined(TARGET_PPC)
+
+#define CPUState CPUPPCState
+#define cpu_init cpu_ppc_init
+#define cpu_exec cpu_ppc_exec
+#define cpu_gen_code cpu_ppc_gen_code
+#define cpu_interrupt cpu_ppc_interrupt
+#define cpu_signal_handler cpu_ppc_signal_handler
+
 #else
 
 #error unsupported target CPU
index 5bbace3..5507c04 100644 (file)
@@ -133,6 +133,7 @@ int cpu_exec(CPUState *env1)
         env->cpsr = psr & ~0xf0000000;
     }
 #elif defined(TARGET_SPARC)
+#elif defined(TARGET_PPC)
 #else
 #error unsupported target CPU
 #endif
@@ -228,6 +229,8 @@ int cpu_exec(CPUState *env1)
                     env->cpsr &= ~0xf0000000;
 #elif defined(TARGET_SPARC)
                     cpu_sparc_dump_state (env, logfile, 0);
+#elif defined(TARGET_PPC)
+                    cpu_ppc_dump_state(env, logfile, 0);
 #else
 #error unsupported target CPU 
 #endif
@@ -246,13 +249,17 @@ int cpu_exec(CPUState *env1)
                 cs_base = 0;
                 pc = (uint8_t *)env->regs[15];
 #elif defined(TARGET_SPARC)
-                               flags = 0;
-                               cs_base = 0;
-                               if (env->npc) {
-                                       env->pc = env->npc;
-                                       env->npc = 0;
-                               }
-                               pc = (uint8_t *) env->pc;
+                flags = 0;
+                cs_base = 0;
+                if (env->npc) {
+                    env->pc = env->npc;
+                    env->npc = 0;
+                }
+                pc = (uint8_t *) env->pc;
+#elif defined(TARGET_PPC)
+                flags = 0;
+                cs_base = 0;
+                pc = (uint8_t *)env->nip;
 #else
 #error unsupported CPU
 #endif
@@ -376,6 +383,7 @@ int cpu_exec(CPUState *env1)
 #elif defined(TARGET_ARM)
     env->cpsr = compute_cpsr();
 #elif defined(TARGET_SPARC)
+#elif defined(TARGET_PPC)
 #else
 #error unsupported target CPU
 #endif
@@ -513,6 +521,43 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
 {
        return 0;
 }
+#elif defined (TARGET_PPC)
+static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+                                    int is_write, sigset_t *old_set)
+{
+    TranslationBlock *tb;
+    
+#if 0
+    if (cpu_single_env)
+        env = cpu_single_env; /* XXX: find a correct solution for multithread */
+#endif
+#if defined(DEBUG_SIGNAL)
+    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
+           pc, address, is_write, *(unsigned long *)old_set);
+#endif
+    /* XXX: locking issue */
+    if (is_write && page_unprotect(address)) {
+        return 1;
+    }
+
+    /* now we have a real cpu fault */
+    tb = tb_find_pc(pc);
+    if (tb) {
+        /* the PC is inside the translated code. It means that we have
+           a virtual CPU fault */
+        cpu_restore_state(tb, env, pc);
+    }
+#if 0
+    printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", 
+           env->eip, env->cr[2], env->error_code);
+#endif
+    /* we restore the process signal mask as the sigreturn should
+       do it (XXX: use sigsetjmp) */
+    sigprocmask(SIG_SETMASK, old_set, NULL);
+    raise_exception_err(EXCP_PROGRAM, env->error_code);
+    /* never comes here */
+    return 1;
+}
 #else
 #error unsupported target CPU
 #endif
diff --git a/disas.c b/disas.c
index d5aa7f3..f274ac5 100644 (file)
--- a/disas.c
+++ b/disas.c
@@ -171,6 +171,8 @@ void disas(FILE *out, void *code, unsigned long size, int is_host, int flags)
        print_insn = print_insn_arm;
 #elif defined(TARGET_SPARC)
        print_insn = print_insn_sparc;
+#elif defined(TARGET_PPC)
+       print_insn = print_insn_ppc;
 #else
        fprintf(out, "Asm output not supported on this arch\n");
        return;
index ec32fbc..2b8ba3a 100644 (file)
@@ -17,6 +17,9 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#if !defined(__DYNGEN_EXEC_H__)
+#define __DYNGEN_EXEC_H__
+
 typedef unsigned char uint8_t;
 typedef unsigned short uint16_t;
 typedef unsigned int uint32_t;
@@ -27,6 +30,19 @@ typedef signed short int16_t;
 typedef signed int int32_t;
 typedef signed long long int64_t;
 
+#define INT8_MIN               (-128)
+#define INT16_MIN              (-32767-1)
+#define INT32_MIN              (-2147483647-1)
+#define INT64_MIN              (-(int64_t)(9223372036854775807)-1)
+#define INT8_MAX               (127)
+#define INT16_MAX              (32767)
+#define INT32_MAX              (2147483647)
+#define INT64_MAX              ((int64_t)(9223372036854775807))
+#define UINT8_MAX              (255)
+#define UINT16_MAX             (65535)
+#define UINT32_MAX             (4294967295U)
+#define UINT64_MAX             ((uint64_t)(18446744073709551615))
+
 #define bswap32(x) \
 ({ \
        uint32_t __x = (x); \
@@ -191,3 +207,5 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
 #ifdef __mc68000
 #define EXIT_TB() asm volatile ("rts")
 #endif
+
+#endif /* !defined(__DYNGEN_EXEC_H__) */
index a0e205c..a7a2f61 100644 (file)
@@ -104,6 +104,46 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 
 #endif
 
+#ifdef TARGET_PPC
+
+#define ELF_START_MMAP 0x80000000
+
+#define elf_check_arch(x) ( (x) == EM_PPC )
+
+#define ELF_CLASS      ELFCLASS32
+#ifdef TARGET_WORDS_BIGENDIAN
+#define ELF_DATA       ELFDATA2MSB
+#else
+#define ELF_DATA       ELFDATA2LSB
+#endif
+#define ELF_ARCH       EM_PPC
+
+/* 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.
+ */
+#define ELF_PLAT_INIT(_r)                                  \
+do {                                                       \
+   unsigned long *pos = (unsigned long *)bprm->p, tmp = 1; \
+    _r->gpr[3] = bprm->argc;                               \
+    _r->gpr[4] = (unsigned long)++pos;                     \
+    for (; tmp != 0; pos++)                                \
+        tmp = *pos;                                        \
+     _r->gpr[5] = (unsigned long)pos;                      \
+} while (0)
+
+static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
+{
+    _regs->msr = 1 << MSR_PR; /* Set user mode */
+    _regs->gpr[1] = infop->start_stack;
+    _regs->nip = infop->entry;
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE      4096
+
+#endif
+
 #include "elf.h"
 
 /*
index 5b75154..aa5b758 100644 (file)
@@ -324,6 +324,127 @@ void cpu_loop (CPUSPARCState *env)
 
 #endif
 
+#ifdef TARGET_PPC
+
+void cpu_loop(CPUPPCState *env)
+{
+    int trapnr;
+    target_siginfo_t info;
+    
+    for(;;) {
+        trapnr = cpu_ppc_exec(env);
+        switch(trapnr) {
+        case EXCP_NONE:
+        case EXCP_INTERRUPT:
+        case EXCP_MTMSR: /* mtmsr instruction:               */
+        case EXCP_BRANCH: /* branch instruction               */
+            /* Single step mode */
+            break;
+#if 0
+        case EXCP_RESET: /* System reset                     */
+            fprintf(stderr, "RESET asked... Stop emulation\n");
+            cpu_ppc_dump_state(env, stderr, 0);
+            abort();
+#endif
+        case EXCP_MACHINE_CHECK: /* Machine check exception          */
+            fprintf(stderr, "Machine check exeption... "
+                    "See you in kernel code !\n");
+            cpu_ppc_dump_state(env, stderr, 0);
+            abort();
+        case EXCP_DSI:  /* Impossible memory access         */
+            fprintf(stderr, "Invalid memory access\n");
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_ILLOPN;
+            info._sifields._sigfault._addr = env->nip;
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_ISI: /* Impossible instruction fetch     */
+            fprintf(stderr, "Invalid instruction fetch\n");
+            info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_ILLOPN;
+            info._sifields._sigfault._addr = env->nip;
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_EXTERNAL: /* External interruption            */
+            fprintf(stderr, "External access exeption\n");
+            cpu_ppc_dump_state(env, stderr, 0);
+            abort();
+        case EXCP_ALIGN: /* Alignment exception              */
+            fprintf(stderr, "Alignment exception\n");
+            cpu_ppc_dump_state(env, stderr, 0);
+            abort();
+        case EXCP_PROGRAM: /* Program exception                */
+            fprintf(stderr, "Program exception\n");
+            cpu_ppc_dump_state(env, stderr, 0);
+            abort();
+            break;
+        /* Trap */
+        case EXCP_TRAP: /* Trap                             */
+        case EXCP_TRACE: /* Trace exception (optional)       */
+            info.si_signo = SIGTRAP;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_ILLOPN;
+            info._sifields._sigfault._addr = env->nip;
+            queue_signal(info.si_signo, &info);
+            break;
+        /* Invalid instruction */
+        case EXCP_INVAL:
+            info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_ILLOPN;
+            info._sifields._sigfault._addr = env->nip;
+            queue_signal(info.si_signo, &info);
+            break;
+        /* Privileged instruction */
+        case EXCP_PRIV: /* Privileged instruction           */
+            info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_ILLOPN;
+            info._sifields._sigfault._addr = env->nip;
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_NO_FP: /* No floating point                */
+        case EXCP_DECR: /* Decrementer exception            */
+        case EXCP_RESA: /* Implementation specific          */
+        case EXCP_RESB: /* Implementation specific          */
+        case EXCP_FP_ASSIST: /* Floating-point assist (optional) */
+            fprintf(stderr, "Misc expt...\n");
+            cpu_ppc_dump_state(env, stderr, 0);
+            abort();
+
+        case EXCP_SYSCALL:
+        {
+            uint32_t ret;
+            /* system call */
+            /* WARNING:
+             * PPC ABI uses overflow flag in cr0 to signal an error
+             * in syscalls.
+             */
+            env->crf[0] &= ~0x1;
+            ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+                             env->gpr[5], env->gpr[6], env->gpr[7],
+                             env->gpr[8]);
+            if (ret > (uint32_t)(-515)) {
+                env->crf[0] |= 0x1;
+                ret = -ret;
+            }
+            env->gpr[3] = ret;
+            break;
+        }
+        default:
+//        error:
+            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 
+                    trapnr);
+            cpu_ppc_dump_state(env, stderr, 0);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+#endif
+
 void usage(void)
 {
     printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
@@ -517,6 +638,16 @@ int main(int argc, char **argv)
 #elif defined(TARGET_SPARC)
        env->pc = regs->u_regs[0];
        env->regwptr[6] = regs->u_regs[1]-0x40;
+#elif defined(TARGET_PPC)
+    {
+        int i;
+        for (i = 0; i < 32; i++)
+            env->msr[i] = (regs->msr >> i) & 1;
+        env->nip = regs->nip;
+        for(i = 0; i < 32; i++) {
+            env->gpr[i] = regs->gpr[i];
+        }
+    }
 #else
 #error unsupported target CPU
 #endif
index d218009..ddf1d9c 100644 (file)
 
 //#define DEBUG
 
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC)
+/* 16 bit uid wrappers emulation */
+#define USE_UID16
+#endif
+
 //#include <linux/msdos_fs.h>
 #define        VFAT_IOCTL_READDIR_BOTH         _IOR('r', 1, struct dirent [2])
 #define        VFAT_IOCTL_READDIR_SHORT        _IOR('r', 2, struct dirent [2])
@@ -1264,7 +1269,16 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
         new_env->regs[13] = newsp;
         new_env->regs[0] = 0;
 #elif defined(TARGET_SPARC)
-               printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
+        printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
+#elif defined(TARGET_PPC)
+        if (!newsp)
+            newsp = env->gpr[1];
+        new_env->gpr[1] = newsp;
+        { 
+            int i;
+            for (i = 7; i < 32; i++)
+                new_env->gpr[i] = 0;
+        }
 #else
 #error unsupported target CPU
 #endif
@@ -1325,11 +1339,41 @@ static long do_fcntl(int fd, int cmd, unsigned long arg)
     return ret;
 }
 
+#ifdef USE_UID16
 
-#define high2lowuid(x) (x)
-#define high2lowgid(x) (x)
-#define low2highuid(x) (x)
-#define low2highgid(x) (x)
+static inline int high2lowuid(int uid)
+{
+    if (uid > 65535)
+        return 65534;
+    else
+        return uid;
+}
+
+static inline int high2lowgid(int gid)
+{
+    if (gid > 65535)
+        return 65534;
+    else
+        return gid;
+}
+
+static inline int low2highuid(int uid)
+{
+    if ((int16_t)uid == -1)
+        return -1;
+    else
+        return uid;
+}
+
+static inline int low2highgid(int gid)
+{
+    if ((int16_t)gid == -1)
+        return -1;
+    else
+        return gid;
+}
+
+#endif /* USE_UID16 */
 
 void syscall_init(void)
 {
@@ -1472,9 +1516,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_chmod:
         ret = get_errno(chmod((const char *)arg1, arg2));
         break;
-    case TARGET_NR_lchown:
-        ret = get_errno(chown((const char *)arg1, arg2, arg3));
-        break;
 #ifdef TARGET_NR_break
     case TARGET_NR_break:
         goto unimplemented;
@@ -1495,12 +1536,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_umount:
         ret = get_errno(umount((const char *)arg1));
         break;
-    case TARGET_NR_setuid:
-        ret = get_errno(setuid(low2highuid(arg1)));
-        break;
-    case TARGET_NR_getuid:
-        ret = get_errno(getuid());
-        break;
     case TARGET_NR_stime:
         {
             int *time_ptr = (int *)arg1;
@@ -1596,20 +1631,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_prof:
         goto unimplemented;
 #endif
-    case TARGET_NR_setgid:
-        ret = get_errno(setgid(low2highgid(arg1)));
-        break;
-    case TARGET_NR_getgid:
-        ret = get_errno(getgid());
-        break;
     case TARGET_NR_signal:
         goto unimplemented;
-    case TARGET_NR_geteuid:
-        ret = get_errno(geteuid());
-        break;
-    case TARGET_NR_getegid:
-        ret = get_errno(getegid());
-        break;
+
     case TARGET_NR_acct:
         goto unimplemented;
     case TARGET_NR_umount2:
@@ -1844,12 +1868,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         /* NOTE: ret is eax, so not transcoding must be done */
         ret = do_rt_sigreturn(cpu_env);
         break;
-    case TARGET_NR_setreuid:
-        ret = get_errno(setreuid(arg1, arg2));
-        break;
-    case TARGET_NR_setregid:
-        ret = get_errno(setregid(arg1, arg2));
-        break;
     case TARGET_NR_sethostname:
         ret = get_errno(sethostname((const char *)arg1, arg2));
         break;
@@ -1906,34 +1924,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
             ret = get_errno(settimeofday(&tv, NULL));
         }
         break;
-    case TARGET_NR_getgroups:
-        {
-            int gidsetsize = arg1;
-            uint16_t *target_grouplist = (void *)arg2;
-            gid_t *grouplist;
-            int i;
-
-            grouplist = alloca(gidsetsize * sizeof(gid_t));
-            ret = get_errno(getgroups(gidsetsize, grouplist));
-            if (!is_error(ret)) {
-                for(i = 0;i < gidsetsize; i++)
-                    target_grouplist[i] = tswap16(grouplist[i]);
-            }
-        }
-        break;
-    case TARGET_NR_setgroups:
-        {
-            int gidsetsize = arg1;
-            uint16_t *target_grouplist = (void *)arg2;
-            gid_t *grouplist;
-            int i;
-
-            grouplist = alloca(gidsetsize * sizeof(gid_t));
-            for(i = 0;i < gidsetsize; i++)
-                grouplist[i] = tswap16(target_grouplist[i]);
-            ret = get_errno(setgroups(gidsetsize, grouplist));
-        }
-        break;
     case TARGET_NR_select:
         {
             struct target_sel_arg_struct *sel = (void *)arg1;
@@ -2026,9 +2016,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_fchmod:
         ret = get_errno(fchmod(arg1, arg2));
         break;
-    case TARGET_NR_fchown:
-        ret = get_errno(fchown(arg1, arg2, arg3));
-        break;
     case TARGET_NR_getpriority:
         ret = get_errno(getpriority(arg1, arg2));
         break;
@@ -2121,10 +2108,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
                 struct target_stat *target_st = (void *)arg2;
                 target_st->st_dev = tswap16(st.st_dev);
                 target_st->st_ino = tswapl(st.st_ino);
+#if defined(TARGET_PPC)
+                target_st->st_mode = tswapl(st.st_mode); /* XXX: check this */
+                target_st->st_uid = tswap32(st.st_uid);
+                target_st->st_gid = tswap32(st.st_gid);
+#else
                 target_st->st_mode = tswap16(st.st_mode);
-                target_st->st_nlink = tswap16(st.st_nlink);
                 target_st->st_uid = tswap16(st.st_uid);
                 target_st->st_gid = tswap16(st.st_gid);
+#endif
+                target_st->st_nlink = tswap16(st.st_nlink);
                 target_st->st_rdev = tswap16(st.st_rdev);
                 target_st->st_size = tswapl(st.st_size);
                 target_st->st_blksize = tswapl(st.st_blksize);
@@ -2230,12 +2223,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         break;
     case TARGET_NR_afs_syscall:
         goto unimplemented;
-    case TARGET_NR_setfsuid:
-        ret = get_errno(setfsuid(arg1));
-        break;
-    case TARGET_NR_setfsgid:
-        ret = get_errno(setfsgid(arg1));
-        break;
     case TARGET_NR__llseek:
         {
             int64_t res;
@@ -2465,52 +2452,13 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
             }
         }
         break;
-#ifdef TARGET_NR_setresuid
-    case TARGET_NR_setresuid:
-        ret = get_errno(setresuid(low2highuid(arg1), 
-                                  low2highuid(arg2), 
-                                  low2highuid(arg3)));
-        break;
-#endif
-#ifdef TARGET_NR_getresuid
-    case TARGET_NR_getresuid:
-        {
-            int ruid, euid, suid;
-            ret = get_errno(getresuid(&ruid, &euid, &suid));
-            if (!is_error(ret)) {
-                *(uint16_t *)arg1 = tswap16(high2lowuid(ruid));
-                *(uint16_t *)arg2 = tswap16(high2lowuid(euid));
-                *(uint16_t *)arg3 = tswap16(high2lowuid(suid));
-            }
-        }
-        break;
-#endif
-#ifdef TARGET_NR_getresgid
-    case TARGET_NR_setresgid:
-        ret = get_errno(setresgid(low2highgid(arg1), 
-                                  low2highgid(arg2), 
-                                  low2highgid(arg3)));
-        break;
-#endif
-#ifdef TARGET_NR_getresgid
-    case TARGET_NR_getresgid:
-        {
-            int rgid, egid, sgid;
-            ret = get_errno(getresgid(&rgid, &egid, &sgid));
-            if (!is_error(ret)) {
-                *(uint16_t *)arg1 = high2lowgid(tswap16(rgid));
-                *(uint16_t *)arg2 = high2lowgid(tswap16(egid));
-                *(uint16_t *)arg3 = high2lowgid(tswap16(sgid));
-            }
-        }
-        break;
-#endif
     case TARGET_NR_query_module:
         goto unimplemented;
     case TARGET_NR_nfsservctl:
         goto unimplemented;
     case TARGET_NR_prctl:
         goto unimplemented;
+#ifdef TARGET_NR_pread
     case TARGET_NR_pread:
         page_unprotect_range((void *)arg2, arg3);
         ret = get_errno(pread(arg1, (void *)arg2, arg3, arg4));
@@ -2518,9 +2466,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_pwrite:
         ret = get_errno(pwrite(arg1, (void *)arg2, arg3, arg4));
         break;
-    case TARGET_NR_chown:
-        ret = get_errno(chown((const char *)arg1, arg2, arg3));
-        break;
+#endif
     case TARGET_NR_getcwd:
         ret = get_errno(sys_getcwd1((char *)arg1, arg2));
         break;
@@ -2594,6 +2540,116 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         }
         break;
 
+#ifdef USE_UID16
+    case TARGET_NR_lchown:
+        ret = get_errno(lchown((const char *)arg1, low2highuid(arg2), low2highgid(arg3)));
+        break;
+    case TARGET_NR_getuid:
+        ret = get_errno(high2lowuid(getuid()));
+        break;
+    case TARGET_NR_getgid:
+        ret = get_errno(high2lowgid(getgid()));
+        break;
+    case TARGET_NR_geteuid:
+        ret = get_errno(high2lowuid(geteuid()));
+        break;
+    case TARGET_NR_getegid:
+        ret = get_errno(high2lowgid(getegid()));
+        break;
+    case TARGET_NR_setreuid:
+        ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
+        break;
+    case TARGET_NR_setregid:
+        ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
+        break;
+    case TARGET_NR_getgroups:
+        {
+            int gidsetsize = arg1;
+            uint16_t *target_grouplist = (void *)arg2;
+            gid_t *grouplist;
+            int i;
+
+            grouplist = alloca(gidsetsize * sizeof(gid_t));
+            ret = get_errno(getgroups(gidsetsize, grouplist));
+            if (!is_error(ret)) {
+                for(i = 0;i < gidsetsize; i++)
+                    target_grouplist[i] = tswap16(grouplist[i]);
+            }
+        }
+        break;
+    case TARGET_NR_setgroups:
+        {
+            int gidsetsize = arg1;
+            uint16_t *target_grouplist = (void *)arg2;
+            gid_t *grouplist;
+            int i;
+
+            grouplist = alloca(gidsetsize * sizeof(gid_t));
+            for(i = 0;i < gidsetsize; i++)
+                grouplist[i] = tswap16(target_grouplist[i]);
+            ret = get_errno(setgroups(gidsetsize, grouplist));
+        }
+        break;
+    case TARGET_NR_fchown:
+        ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
+        break;
+#ifdef TARGET_NR_setresuid
+    case TARGET_NR_setresuid:
+        ret = get_errno(setresuid(low2highuid(arg1), 
+                                  low2highuid(arg2), 
+                                  low2highuid(arg3)));
+        break;
+#endif
+#ifdef TARGET_NR_getresuid
+    case TARGET_NR_getresuid:
+        {
+            int ruid, euid, suid;
+            ret = get_errno(getresuid(&ruid, &euid, &suid));
+            if (!is_error(ret)) {
+                *(uint16_t *)arg1 = tswap16(high2lowuid(ruid));
+                *(uint16_t *)arg2 = tswap16(high2lowuid(euid));
+                *(uint16_t *)arg3 = tswap16(high2lowuid(suid));
+            }
+        }
+        break;
+#endif
+#ifdef TARGET_NR_getresgid
+    case TARGET_NR_setresgid:
+        ret = get_errno(setresgid(low2highgid(arg1), 
+                                  low2highgid(arg2), 
+                                  low2highgid(arg3)));
+        break;
+#endif
+#ifdef TARGET_NR_getresgid
+    case TARGET_NR_getresgid:
+        {
+            int rgid, egid, sgid;
+            ret = get_errno(getresgid(&rgid, &egid, &sgid));
+            if (!is_error(ret)) {
+                *(uint16_t *)arg1 = tswap16(high2lowgid(rgid));
+                *(uint16_t *)arg2 = tswap16(high2lowgid(egid));
+                *(uint16_t *)arg3 = tswap16(high2lowgid(sgid));
+            }
+        }
+        break;
+#endif
+    case TARGET_NR_chown:
+        ret = get_errno(chown((const char *)arg1, low2highuid(arg2), low2highgid(arg3)));
+        break;
+    case TARGET_NR_setuid:
+        ret = get_errno(setuid(low2highuid(arg1)));
+        break;
+    case TARGET_NR_setgid:
+        ret = get_errno(setgid(low2highgid(arg1)));
+        break;
+    case TARGET_NR_setfsuid:
+        ret = get_errno(setfsuid(arg1));
+        break;
+    case TARGET_NR_setfsgid:
+        ret = get_errno(setfsgid(arg1));
+        break;
+#endif /* USE_UID16 */
+
     case TARGET_NR_lchown32:
         ret = get_errno(lchown((const char *)arg1, arg2, arg3));
         break;
@@ -2665,6 +2721,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_setfsgid32:
         ret = get_errno(setfsgid(arg1));
         break;
+
     case TARGET_NR_pivot_root:
         goto unimplemented;
     case TARGET_NR_mincore:
index 8f6d14e..caa40d1 100644 (file)
@@ -279,7 +279,7 @@ struct target_sigaction;
 int do_sigaction(int sig, const struct target_sigaction *act,
                  struct target_sigaction *oact);
 
-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC)
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC)
 
 #define TARGET_SA_NOCLDSTOP    0x00000001
 #define TARGET_SA_NOCLDWAIT    0x00000002 /* not supported yet */
@@ -664,7 +664,7 @@ struct target_pollfd {
 #define TARGET_HDIO_SET_PIO_MODE      0x0327  /* reconfig interface to new speed */
 
 
-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC)
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC)
 
 /* 0x54 is just a magic number to make these relatively unique ('T') */
 
@@ -891,6 +891,9 @@ struct target_termios {
 #define TARGET_MAP_LOCKED      0x2000          /* pages are locked */
 #define TARGET_MAP_NORESERVE   0x4000          /* don't check for reservations */
 
+#endif /* defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) */
+
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC)
 struct target_stat {
        unsigned short st_dev;
        unsigned short __pad1;
@@ -951,7 +954,62 @@ struct target_stat64 {
        unsigned long long      st_ino;
 } __attribute__((packed));
 
-#endif /* defined(TARGET_I386) || defined(TARGET_ARM) */
+#elif defined(TARGET_PPC)
+
+struct target_stat {
+       unsigned short st_dev;
+       target_ulong st_ino;
+       unsigned int st_mode;
+       unsigned short st_nlink;
+       unsigned int st_uid;
+       unsigned int st_gid;
+       unsigned short st_rdev;
+       target_ulong  st_size;
+       target_ulong  st_blksize;
+       target_ulong  st_blocks;
+       target_ulong  target_st_atime;
+       target_ulong  __unused1;
+       target_ulong  target_st_mtime;
+       target_ulong  __unused2;
+       target_ulong  target_st_ctime;
+       target_ulong  __unused3;
+       target_ulong  __unused4;
+       target_ulong  __unused5;
+};
+
+struct target_stat64 {
+       unsigned long long st_dev;
+
+        unsigned long long st_ino;
+
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+
+       unsigned int st_uid;
+       unsigned int st_gid;
+
+       unsigned long long      st_rdev;
+       unsigned short int __pad2;
+
+       long long       st_size;
+       target_ulong    st_blksize;
+
+       long long       st_blocks;      /* Number 512-byte blocks allocated. */
+
+       target_ulong    target_st_atime;
+        target_ulong    target_st_atime_nsec;
+
+       target_ulong    target_st_mtime;
+        target_ulong    target_st_mtime_nsec;
+
+       target_ulong    target_st_ctime;
+        target_ulong    target_st_ctime_nsec;
+
+        target_ulong    __unused4;
+        target_ulong    __unused5;
+};
+
+#endif /* defined(TARGET_PPC) */
 
 #define TARGET_F_DUPFD         0       /* dup */
 #define TARGET_F_GETFD         1       /* get close_on_exec */