aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog3
-rw-r--r--Makefile.target4
-rwxr-xr-xconfigure7
-rw-r--r--cpu-all.h9
-rw-r--r--cpu-exec.c59
-rw-r--r--disas.c2
-rw-r--r--dyngen-exec.h18
-rw-r--r--linux-user/elfload.c40
-rw-r--r--linux-user/main.c131
-rw-r--r--linux-user/syscall.c283
-rw-r--r--linux-user/syscall_defs.h64
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 <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:
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 */