From 678673089d1ba7cd0f2960a2815a0d5bb8a72fa3 Mon Sep 17 00:00:00 2001 From: bellard Date: Sun, 23 Nov 2003 17:05:30 +0000 Subject: PowerPC target support (Jocelyn Mayer) - added better support for uid16 git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@474 c046a42c-6fe2-441c-8c8c-71466251a162 --- Changelog | 3 +- Makefile.target | 4 + configure | 7 +- cpu-all.h | 9 ++ cpu-exec.c | 59 ++++++++-- disas.c | 2 + dyngen-exec.h | 18 +++ linux-user/elfload.c | 40 +++++++ linux-user/main.c | 131 +++++++++++++++++++++ linux-user/syscall.c | 283 ++++++++++++++++++++++++++++------------------ linux-user/syscall_defs.h | 64 ++++++++++- 11 files changed, 495 insertions(+), 125 deletions(-) diff --git a/Changelog b/Changelog index 3c98c5cf63..401f364cc8 100644 --- 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: diff --git a/Makefile.target b/Makefile.target index b88887641f..eb2e6db12a 100644 --- a/Makefile.target +++ b/Makefile.target @@ -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) diff --git a/configure b/configure index 3c9a29876d..05bc3b6a67 100755 --- 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 diff --git a/cpu-all.h b/cpu-all.h index c7491a00cf..9c880824fe 100644 --- 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 diff --git a/cpu-exec.c b/cpu-exec.c index 5bbace345f..5507c04dd0 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -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 d5aa7f3713..f274ac52d1 100644 --- 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; diff --git a/dyngen-exec.h b/dyngen-exec.h index ec32fbc9e9..2b8ba3a3ef 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -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__) */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index a0e205cd67..a7a2f61eb4 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -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" /* diff --git a/linux-user/main.c b/linux-user/main.c index 5b751541ee..aa5b758d64 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -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 diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d218009ad6..ddf1d9c52d 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -65,6 +65,11 @@ //#define DEBUG +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) +/* 16 bit uid wrappers emulation */ +#define USE_UID16 +#endif + //#include #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: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 8f6d14e553..caa40d1f0b 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -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 */ -- cgit v1.2.1