Commit 678673089d1ba7cd0f2960a2815a0d5bb8a72fa3
1 parent
28b6751f
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
Showing
11 changed files
with
495 additions
and
125 deletions
Changelog
| @@ -9,7 +9,8 @@ version 0.5.1: | @@ -9,7 +9,8 @@ version 0.5.1: | ||
| 9 | - IRET and INT fixes in VM86 mode with IOPL=3 | 9 | - IRET and INT fixes in VM86 mode with IOPL=3 |
| 10 | - Port I/Os use TSS io map | 10 | - Port I/Os use TSS io map |
| 11 | - Full task switching/task gate support | 11 | - Full task switching/task gate support |
| 12 | - - added verr, verw, arpl | 12 | + - added verr, verw, arpl, fcmovxx |
| 13 | + - PowerPC target support (Jocelyn Mayer) | ||
| 13 | 14 | ||
| 14 | version 0.5.0: | 15 | version 0.5.0: |
| 15 | 16 |
Makefile.target
| @@ -146,6 +146,10 @@ ifeq ($(TARGET_ARCH), i386) | @@ -146,6 +146,10 @@ ifeq ($(TARGET_ARCH), i386) | ||
| 146 | LIBOBJS+=helper.o helper2.o | 146 | LIBOBJS+=helper.o helper2.o |
| 147 | endif | 147 | endif |
| 148 | 148 | ||
| 149 | +ifeq ($(TARGET_ARCH), ppc) | ||
| 150 | +LIBOBJS+=helper.o | ||
| 151 | +endif | ||
| 152 | + | ||
| 149 | # NOTE: the disassembler code is only needed for debugging | 153 | # NOTE: the disassembler code is only needed for debugging |
| 150 | LIBOBJS+=disas.o | 154 | LIBOBJS+=disas.o |
| 151 | ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386) | 155 | ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386) |
configure
| @@ -27,7 +27,7 @@ ar="ar" | @@ -27,7 +27,7 @@ ar="ar" | ||
| 27 | make="make" | 27 | make="make" |
| 28 | strip="strip" | 28 | strip="strip" |
| 29 | cpu=`uname -m` | 29 | cpu=`uname -m` |
| 30 | -target_list="i386-user i386 i386-softmmu arm-user sparc-user" | 30 | +target_list="i386-user i386 i386-softmmu arm-user sparc-user ppc-user" |
| 31 | case "$cpu" in | 31 | case "$cpu" in |
| 32 | i386|i486|i586|i686|i86pc|BePC) | 32 | i386|i486|i586|i686|i86pc|BePC) |
| 33 | cpu="i386" | 33 | cpu="i386" |
| @@ -322,6 +322,7 @@ config_h=$target_dir/config.h | @@ -322,6 +322,7 @@ config_h=$target_dir/config.h | ||
| 322 | target_cpu=`echo $target | cut -d '-' -f 1` | 322 | target_cpu=`echo $target | cut -d '-' -f 1` |
| 323 | target_bigendian="no" | 323 | target_bigendian="no" |
| 324 | [ "$target_cpu" = "sparc" ] && target_bigendian=yes | 324 | [ "$target_cpu" = "sparc" ] && target_bigendian=yes |
| 325 | +[ "$target_cpu" = "ppc" ] && target_bigendian=yes | ||
| 325 | target_softmmu="no" | 326 | target_softmmu="no" |
| 326 | if expr $target : '.*-softmmu' > /dev/null ; then | 327 | if expr $target : '.*-softmmu' > /dev/null ; then |
| 327 | target_softmmu="yes" | 328 | target_softmmu="yes" |
| @@ -358,6 +359,10 @@ elif test "$target_cpu" = "sparc" ; then | @@ -358,6 +359,10 @@ elif test "$target_cpu" = "sparc" ; then | ||
| 358 | echo "TARGET_ARCH=sparc" >> $config_mak | 359 | echo "TARGET_ARCH=sparc" >> $config_mak |
| 359 | echo "#define TARGET_ARCH \"sparc\"" >> $config_h | 360 | echo "#define TARGET_ARCH \"sparc\"" >> $config_h |
| 360 | echo "#define TARGET_SPARC 1" >> $config_h | 361 | echo "#define TARGET_SPARC 1" >> $config_h |
| 362 | +elif test "$target_cpu" = "ppc" ; then | ||
| 363 | + echo "TARGET_ARCH=ppc" >> $config_mak | ||
| 364 | + echo "#define TARGET_ARCH \"ppc\"" >> $config_h | ||
| 365 | + echo "#define TARGET_PPC 1" >> $config_h | ||
| 361 | else | 366 | else |
| 362 | echo "Unsupported target CPU" | 367 | echo "Unsupported target CPU" |
| 363 | exit 1 | 368 | exit 1 |
cpu-all.h
| @@ -395,6 +395,15 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size); | @@ -395,6 +395,15 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size); | ||
| 395 | #define cpu_interrupt cpu_sparc_interrupt | 395 | #define cpu_interrupt cpu_sparc_interrupt |
| 396 | #define cpu_signal_handler cpu_sparc_signal_handler | 396 | #define cpu_signal_handler cpu_sparc_signal_handler |
| 397 | 397 | ||
| 398 | +#elif defined(TARGET_PPC) | ||
| 399 | + | ||
| 400 | +#define CPUState CPUPPCState | ||
| 401 | +#define cpu_init cpu_ppc_init | ||
| 402 | +#define cpu_exec cpu_ppc_exec | ||
| 403 | +#define cpu_gen_code cpu_ppc_gen_code | ||
| 404 | +#define cpu_interrupt cpu_ppc_interrupt | ||
| 405 | +#define cpu_signal_handler cpu_ppc_signal_handler | ||
| 406 | + | ||
| 398 | #else | 407 | #else |
| 399 | 408 | ||
| 400 | #error unsupported target CPU | 409 | #error unsupported target CPU |
cpu-exec.c
| @@ -133,6 +133,7 @@ int cpu_exec(CPUState *env1) | @@ -133,6 +133,7 @@ int cpu_exec(CPUState *env1) | ||
| 133 | env->cpsr = psr & ~0xf0000000; | 133 | env->cpsr = psr & ~0xf0000000; |
| 134 | } | 134 | } |
| 135 | #elif defined(TARGET_SPARC) | 135 | #elif defined(TARGET_SPARC) |
| 136 | +#elif defined(TARGET_PPC) | ||
| 136 | #else | 137 | #else |
| 137 | #error unsupported target CPU | 138 | #error unsupported target CPU |
| 138 | #endif | 139 | #endif |
| @@ -228,6 +229,8 @@ int cpu_exec(CPUState *env1) | @@ -228,6 +229,8 @@ int cpu_exec(CPUState *env1) | ||
| 228 | env->cpsr &= ~0xf0000000; | 229 | env->cpsr &= ~0xf0000000; |
| 229 | #elif defined(TARGET_SPARC) | 230 | #elif defined(TARGET_SPARC) |
| 230 | cpu_sparc_dump_state (env, logfile, 0); | 231 | cpu_sparc_dump_state (env, logfile, 0); |
| 232 | +#elif defined(TARGET_PPC) | ||
| 233 | + cpu_ppc_dump_state(env, logfile, 0); | ||
| 231 | #else | 234 | #else |
| 232 | #error unsupported target CPU | 235 | #error unsupported target CPU |
| 233 | #endif | 236 | #endif |
| @@ -246,13 +249,17 @@ int cpu_exec(CPUState *env1) | @@ -246,13 +249,17 @@ int cpu_exec(CPUState *env1) | ||
| 246 | cs_base = 0; | 249 | cs_base = 0; |
| 247 | pc = (uint8_t *)env->regs[15]; | 250 | pc = (uint8_t *)env->regs[15]; |
| 248 | #elif defined(TARGET_SPARC) | 251 | #elif defined(TARGET_SPARC) |
| 249 | - flags = 0; | ||
| 250 | - cs_base = 0; | ||
| 251 | - if (env->npc) { | ||
| 252 | - env->pc = env->npc; | ||
| 253 | - env->npc = 0; | ||
| 254 | - } | ||
| 255 | - pc = (uint8_t *) env->pc; | 252 | + flags = 0; |
| 253 | + cs_base = 0; | ||
| 254 | + if (env->npc) { | ||
| 255 | + env->pc = env->npc; | ||
| 256 | + env->npc = 0; | ||
| 257 | + } | ||
| 258 | + pc = (uint8_t *) env->pc; | ||
| 259 | +#elif defined(TARGET_PPC) | ||
| 260 | + flags = 0; | ||
| 261 | + cs_base = 0; | ||
| 262 | + pc = (uint8_t *)env->nip; | ||
| 256 | #else | 263 | #else |
| 257 | #error unsupported CPU | 264 | #error unsupported CPU |
| 258 | #endif | 265 | #endif |
| @@ -376,6 +383,7 @@ int cpu_exec(CPUState *env1) | @@ -376,6 +383,7 @@ int cpu_exec(CPUState *env1) | ||
| 376 | #elif defined(TARGET_ARM) | 383 | #elif defined(TARGET_ARM) |
| 377 | env->cpsr = compute_cpsr(); | 384 | env->cpsr = compute_cpsr(); |
| 378 | #elif defined(TARGET_SPARC) | 385 | #elif defined(TARGET_SPARC) |
| 386 | +#elif defined(TARGET_PPC) | ||
| 379 | #else | 387 | #else |
| 380 | #error unsupported target CPU | 388 | #error unsupported target CPU |
| 381 | #endif | 389 | #endif |
| @@ -513,6 +521,43 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | @@ -513,6 +521,43 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | ||
| 513 | { | 521 | { |
| 514 | return 0; | 522 | return 0; |
| 515 | } | 523 | } |
| 524 | +#elif defined (TARGET_PPC) | ||
| 525 | +static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | ||
| 526 | + int is_write, sigset_t *old_set) | ||
| 527 | +{ | ||
| 528 | + TranslationBlock *tb; | ||
| 529 | + | ||
| 530 | +#if 0 | ||
| 531 | + if (cpu_single_env) | ||
| 532 | + env = cpu_single_env; /* XXX: find a correct solution for multithread */ | ||
| 533 | +#endif | ||
| 534 | +#if defined(DEBUG_SIGNAL) | ||
| 535 | + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", | ||
| 536 | + pc, address, is_write, *(unsigned long *)old_set); | ||
| 537 | +#endif | ||
| 538 | + /* XXX: locking issue */ | ||
| 539 | + if (is_write && page_unprotect(address)) { | ||
| 540 | + return 1; | ||
| 541 | + } | ||
| 542 | + | ||
| 543 | + /* now we have a real cpu fault */ | ||
| 544 | + tb = tb_find_pc(pc); | ||
| 545 | + if (tb) { | ||
| 546 | + /* the PC is inside the translated code. It means that we have | ||
| 547 | + a virtual CPU fault */ | ||
| 548 | + cpu_restore_state(tb, env, pc); | ||
| 549 | + } | ||
| 550 | +#if 0 | ||
| 551 | + printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", | ||
| 552 | + env->eip, env->cr[2], env->error_code); | ||
| 553 | +#endif | ||
| 554 | + /* we restore the process signal mask as the sigreturn should | ||
| 555 | + do it (XXX: use sigsetjmp) */ | ||
| 556 | + sigprocmask(SIG_SETMASK, old_set, NULL); | ||
| 557 | + raise_exception_err(EXCP_PROGRAM, env->error_code); | ||
| 558 | + /* never comes here */ | ||
| 559 | + return 1; | ||
| 560 | +} | ||
| 516 | #else | 561 | #else |
| 517 | #error unsupported target CPU | 562 | #error unsupported target CPU |
| 518 | #endif | 563 | #endif |
disas.c
| @@ -171,6 +171,8 @@ void disas(FILE *out, void *code, unsigned long size, int is_host, int flags) | @@ -171,6 +171,8 @@ void disas(FILE *out, void *code, unsigned long size, int is_host, int flags) | ||
| 171 | print_insn = print_insn_arm; | 171 | print_insn = print_insn_arm; |
| 172 | #elif defined(TARGET_SPARC) | 172 | #elif defined(TARGET_SPARC) |
| 173 | print_insn = print_insn_sparc; | 173 | print_insn = print_insn_sparc; |
| 174 | +#elif defined(TARGET_PPC) | ||
| 175 | + print_insn = print_insn_ppc; | ||
| 174 | #else | 176 | #else |
| 175 | fprintf(out, "Asm output not supported on this arch\n"); | 177 | fprintf(out, "Asm output not supported on this arch\n"); |
| 176 | return; | 178 | return; |
dyngen-exec.h
| @@ -17,6 +17,9 @@ | @@ -17,6 +17,9 @@ | ||
| 17 | * License along with this library; if not, write to the Free Software | 17 | * License along with this library; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | +#if !defined(__DYNGEN_EXEC_H__) | ||
| 21 | +#define __DYNGEN_EXEC_H__ | ||
| 22 | + | ||
| 20 | typedef unsigned char uint8_t; | 23 | typedef unsigned char uint8_t; |
| 21 | typedef unsigned short uint16_t; | 24 | typedef unsigned short uint16_t; |
| 22 | typedef unsigned int uint32_t; | 25 | typedef unsigned int uint32_t; |
| @@ -27,6 +30,19 @@ typedef signed short int16_t; | @@ -27,6 +30,19 @@ typedef signed short int16_t; | ||
| 27 | typedef signed int int32_t; | 30 | typedef signed int int32_t; |
| 28 | typedef signed long long int64_t; | 31 | typedef signed long long int64_t; |
| 29 | 32 | ||
| 33 | +#define INT8_MIN (-128) | ||
| 34 | +#define INT16_MIN (-32767-1) | ||
| 35 | +#define INT32_MIN (-2147483647-1) | ||
| 36 | +#define INT64_MIN (-(int64_t)(9223372036854775807)-1) | ||
| 37 | +#define INT8_MAX (127) | ||
| 38 | +#define INT16_MAX (32767) | ||
| 39 | +#define INT32_MAX (2147483647) | ||
| 40 | +#define INT64_MAX ((int64_t)(9223372036854775807)) | ||
| 41 | +#define UINT8_MAX (255) | ||
| 42 | +#define UINT16_MAX (65535) | ||
| 43 | +#define UINT32_MAX (4294967295U) | ||
| 44 | +#define UINT64_MAX ((uint64_t)(18446744073709551615)) | ||
| 45 | + | ||
| 30 | #define bswap32(x) \ | 46 | #define bswap32(x) \ |
| 31 | ({ \ | 47 | ({ \ |
| 32 | uint32_t __x = (x); \ | 48 | uint32_t __x = (x); \ |
| @@ -191,3 +207,5 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; | @@ -191,3 +207,5 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; | ||
| 191 | #ifdef __mc68000 | 207 | #ifdef __mc68000 |
| 192 | #define EXIT_TB() asm volatile ("rts") | 208 | #define EXIT_TB() asm volatile ("rts") |
| 193 | #endif | 209 | #endif |
| 210 | + | ||
| 211 | +#endif /* !defined(__DYNGEN_EXEC_H__) */ |
linux-user/elfload.c
| @@ -104,6 +104,46 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i | @@ -104,6 +104,46 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i | ||
| 104 | 104 | ||
| 105 | #endif | 105 | #endif |
| 106 | 106 | ||
| 107 | +#ifdef TARGET_PPC | ||
| 108 | + | ||
| 109 | +#define ELF_START_MMAP 0x80000000 | ||
| 110 | + | ||
| 111 | +#define elf_check_arch(x) ( (x) == EM_PPC ) | ||
| 112 | + | ||
| 113 | +#define ELF_CLASS ELFCLASS32 | ||
| 114 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 115 | +#define ELF_DATA ELFDATA2MSB | ||
| 116 | +#else | ||
| 117 | +#define ELF_DATA ELFDATA2LSB | ||
| 118 | +#endif | ||
| 119 | +#define ELF_ARCH EM_PPC | ||
| 120 | + | ||
| 121 | +/* Note that isn't exactly what regular kernel does | ||
| 122 | + * but this is what the ABI wants and is needed to allow | ||
| 123 | + * execution of PPC BSD programs. | ||
| 124 | + */ | ||
| 125 | +#define ELF_PLAT_INIT(_r) \ | ||
| 126 | +do { \ | ||
| 127 | + unsigned long *pos = (unsigned long *)bprm->p, tmp = 1; \ | ||
| 128 | + _r->gpr[3] = bprm->argc; \ | ||
| 129 | + _r->gpr[4] = (unsigned long)++pos; \ | ||
| 130 | + for (; tmp != 0; pos++) \ | ||
| 131 | + tmp = *pos; \ | ||
| 132 | + _r->gpr[5] = (unsigned long)pos; \ | ||
| 133 | +} while (0) | ||
| 134 | + | ||
| 135 | +static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) | ||
| 136 | +{ | ||
| 137 | + _regs->msr = 1 << MSR_PR; /* Set user mode */ | ||
| 138 | + _regs->gpr[1] = infop->start_stack; | ||
| 139 | + _regs->nip = infop->entry; | ||
| 140 | +} | ||
| 141 | + | ||
| 142 | +#define USE_ELF_CORE_DUMP | ||
| 143 | +#define ELF_EXEC_PAGESIZE 4096 | ||
| 144 | + | ||
| 145 | +#endif | ||
| 146 | + | ||
| 107 | #include "elf.h" | 147 | #include "elf.h" |
| 108 | 148 | ||
| 109 | /* | 149 | /* |
linux-user/main.c
| @@ -324,6 +324,127 @@ void cpu_loop (CPUSPARCState *env) | @@ -324,6 +324,127 @@ void cpu_loop (CPUSPARCState *env) | ||
| 324 | 324 | ||
| 325 | #endif | 325 | #endif |
| 326 | 326 | ||
| 327 | +#ifdef TARGET_PPC | ||
| 328 | + | ||
| 329 | +void cpu_loop(CPUPPCState *env) | ||
| 330 | +{ | ||
| 331 | + int trapnr; | ||
| 332 | + target_siginfo_t info; | ||
| 333 | + | ||
| 334 | + for(;;) { | ||
| 335 | + trapnr = cpu_ppc_exec(env); | ||
| 336 | + switch(trapnr) { | ||
| 337 | + case EXCP_NONE: | ||
| 338 | + case EXCP_INTERRUPT: | ||
| 339 | + case EXCP_MTMSR: /* mtmsr instruction: */ | ||
| 340 | + case EXCP_BRANCH: /* branch instruction */ | ||
| 341 | + /* Single step mode */ | ||
| 342 | + break; | ||
| 343 | +#if 0 | ||
| 344 | + case EXCP_RESET: /* System reset */ | ||
| 345 | + fprintf(stderr, "RESET asked... Stop emulation\n"); | ||
| 346 | + cpu_ppc_dump_state(env, stderr, 0); | ||
| 347 | + abort(); | ||
| 348 | +#endif | ||
| 349 | + case EXCP_MACHINE_CHECK: /* Machine check exception */ | ||
| 350 | + fprintf(stderr, "Machine check exeption... " | ||
| 351 | + "See you in kernel code !\n"); | ||
| 352 | + cpu_ppc_dump_state(env, stderr, 0); | ||
| 353 | + abort(); | ||
| 354 | + case EXCP_DSI: /* Impossible memory access */ | ||
| 355 | + fprintf(stderr, "Invalid memory access\n"); | ||
| 356 | + info.si_signo = SIGSEGV; | ||
| 357 | + info.si_errno = 0; | ||
| 358 | + info.si_code = TARGET_ILL_ILLOPN; | ||
| 359 | + info._sifields._sigfault._addr = env->nip; | ||
| 360 | + queue_signal(info.si_signo, &info); | ||
| 361 | + break; | ||
| 362 | + case EXCP_ISI: /* Impossible instruction fetch */ | ||
| 363 | + fprintf(stderr, "Invalid instruction fetch\n"); | ||
| 364 | + info.si_signo = SIGBUS; | ||
| 365 | + info.si_errno = 0; | ||
| 366 | + info.si_code = TARGET_ILL_ILLOPN; | ||
| 367 | + info._sifields._sigfault._addr = env->nip; | ||
| 368 | + queue_signal(info.si_signo, &info); | ||
| 369 | + break; | ||
| 370 | + case EXCP_EXTERNAL: /* External interruption */ | ||
| 371 | + fprintf(stderr, "External access exeption\n"); | ||
| 372 | + cpu_ppc_dump_state(env, stderr, 0); | ||
| 373 | + abort(); | ||
| 374 | + case EXCP_ALIGN: /* Alignment exception */ | ||
| 375 | + fprintf(stderr, "Alignment exception\n"); | ||
| 376 | + cpu_ppc_dump_state(env, stderr, 0); | ||
| 377 | + abort(); | ||
| 378 | + case EXCP_PROGRAM: /* Program exception */ | ||
| 379 | + fprintf(stderr, "Program exception\n"); | ||
| 380 | + cpu_ppc_dump_state(env, stderr, 0); | ||
| 381 | + abort(); | ||
| 382 | + break; | ||
| 383 | + /* Trap */ | ||
| 384 | + case EXCP_TRAP: /* Trap */ | ||
| 385 | + case EXCP_TRACE: /* Trace exception (optional) */ | ||
| 386 | + info.si_signo = SIGTRAP; | ||
| 387 | + info.si_errno = 0; | ||
| 388 | + info.si_code = TARGET_ILL_ILLOPN; | ||
| 389 | + info._sifields._sigfault._addr = env->nip; | ||
| 390 | + queue_signal(info.si_signo, &info); | ||
| 391 | + break; | ||
| 392 | + /* Invalid instruction */ | ||
| 393 | + case EXCP_INVAL: | ||
| 394 | + info.si_signo = SIGILL; | ||
| 395 | + info.si_errno = 0; | ||
| 396 | + info.si_code = TARGET_ILL_ILLOPN; | ||
| 397 | + info._sifields._sigfault._addr = env->nip; | ||
| 398 | + queue_signal(info.si_signo, &info); | ||
| 399 | + break; | ||
| 400 | + /* Privileged instruction */ | ||
| 401 | + case EXCP_PRIV: /* Privileged instruction */ | ||
| 402 | + info.si_signo = SIGILL; | ||
| 403 | + info.si_errno = 0; | ||
| 404 | + info.si_code = TARGET_ILL_ILLOPN; | ||
| 405 | + info._sifields._sigfault._addr = env->nip; | ||
| 406 | + queue_signal(info.si_signo, &info); | ||
| 407 | + break; | ||
| 408 | + case EXCP_NO_FP: /* No floating point */ | ||
| 409 | + case EXCP_DECR: /* Decrementer exception */ | ||
| 410 | + case EXCP_RESA: /* Implementation specific */ | ||
| 411 | + case EXCP_RESB: /* Implementation specific */ | ||
| 412 | + case EXCP_FP_ASSIST: /* Floating-point assist (optional) */ | ||
| 413 | + fprintf(stderr, "Misc expt...\n"); | ||
| 414 | + cpu_ppc_dump_state(env, stderr, 0); | ||
| 415 | + abort(); | ||
| 416 | + | ||
| 417 | + case EXCP_SYSCALL: | ||
| 418 | + { | ||
| 419 | + uint32_t ret; | ||
| 420 | + /* system call */ | ||
| 421 | + /* WARNING: | ||
| 422 | + * PPC ABI uses overflow flag in cr0 to signal an error | ||
| 423 | + * in syscalls. | ||
| 424 | + */ | ||
| 425 | + env->crf[0] &= ~0x1; | ||
| 426 | + ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], | ||
| 427 | + env->gpr[5], env->gpr[6], env->gpr[7], | ||
| 428 | + env->gpr[8]); | ||
| 429 | + if (ret > (uint32_t)(-515)) { | ||
| 430 | + env->crf[0] |= 0x1; | ||
| 431 | + ret = -ret; | ||
| 432 | + } | ||
| 433 | + env->gpr[3] = ret; | ||
| 434 | + break; | ||
| 435 | + } | ||
| 436 | + default: | ||
| 437 | +// error: | ||
| 438 | + fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", | ||
| 439 | + trapnr); | ||
| 440 | + cpu_ppc_dump_state(env, stderr, 0); | ||
| 441 | + abort(); | ||
| 442 | + } | ||
| 443 | + process_pending_signals(env); | ||
| 444 | + } | ||
| 445 | +} | ||
| 446 | +#endif | ||
| 447 | + | ||
| 327 | void usage(void) | 448 | void usage(void) |
| 328 | { | 449 | { |
| 329 | printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" | 450 | printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" |
| @@ -517,6 +638,16 @@ int main(int argc, char **argv) | @@ -517,6 +638,16 @@ int main(int argc, char **argv) | ||
| 517 | #elif defined(TARGET_SPARC) | 638 | #elif defined(TARGET_SPARC) |
| 518 | env->pc = regs->u_regs[0]; | 639 | env->pc = regs->u_regs[0]; |
| 519 | env->regwptr[6] = regs->u_regs[1]-0x40; | 640 | env->regwptr[6] = regs->u_regs[1]-0x40; |
| 641 | +#elif defined(TARGET_PPC) | ||
| 642 | + { | ||
| 643 | + int i; | ||
| 644 | + for (i = 0; i < 32; i++) | ||
| 645 | + env->msr[i] = (regs->msr >> i) & 1; | ||
| 646 | + env->nip = regs->nip; | ||
| 647 | + for(i = 0; i < 32; i++) { | ||
| 648 | + env->gpr[i] = regs->gpr[i]; | ||
| 649 | + } | ||
| 650 | + } | ||
| 520 | #else | 651 | #else |
| 521 | #error unsupported target CPU | 652 | #error unsupported target CPU |
| 522 | #endif | 653 | #endif |
linux-user/syscall.c
| @@ -65,6 +65,11 @@ | @@ -65,6 +65,11 @@ | ||
| 65 | 65 | ||
| 66 | //#define DEBUG | 66 | //#define DEBUG |
| 67 | 67 | ||
| 68 | +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) | ||
| 69 | +/* 16 bit uid wrappers emulation */ | ||
| 70 | +#define USE_UID16 | ||
| 71 | +#endif | ||
| 72 | + | ||
| 68 | //#include <linux/msdos_fs.h> | 73 | //#include <linux/msdos_fs.h> |
| 69 | #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) | 74 | #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) |
| 70 | #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) | 75 | #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) | @@ -1264,7 +1269,16 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp) | ||
| 1264 | new_env->regs[13] = newsp; | 1269 | new_env->regs[13] = newsp; |
| 1265 | new_env->regs[0] = 0; | 1270 | new_env->regs[0] = 0; |
| 1266 | #elif defined(TARGET_SPARC) | 1271 | #elif defined(TARGET_SPARC) |
| 1267 | - printf ("HELPME: %s:%d\n", __FILE__, __LINE__); | 1272 | + printf ("HELPME: %s:%d\n", __FILE__, __LINE__); |
| 1273 | +#elif defined(TARGET_PPC) | ||
| 1274 | + if (!newsp) | ||
| 1275 | + newsp = env->gpr[1]; | ||
| 1276 | + new_env->gpr[1] = newsp; | ||
| 1277 | + { | ||
| 1278 | + int i; | ||
| 1279 | + for (i = 7; i < 32; i++) | ||
| 1280 | + new_env->gpr[i] = 0; | ||
| 1281 | + } | ||
| 1268 | #else | 1282 | #else |
| 1269 | #error unsupported target CPU | 1283 | #error unsupported target CPU |
| 1270 | #endif | 1284 | #endif |
| @@ -1325,11 +1339,41 @@ static long do_fcntl(int fd, int cmd, unsigned long arg) | @@ -1325,11 +1339,41 @@ static long do_fcntl(int fd, int cmd, unsigned long arg) | ||
| 1325 | return ret; | 1339 | return ret; |
| 1326 | } | 1340 | } |
| 1327 | 1341 | ||
| 1342 | +#ifdef USE_UID16 | ||
| 1328 | 1343 | ||
| 1329 | -#define high2lowuid(x) (x) | ||
| 1330 | -#define high2lowgid(x) (x) | ||
| 1331 | -#define low2highuid(x) (x) | ||
| 1332 | -#define low2highgid(x) (x) | 1344 | +static inline int high2lowuid(int uid) |
| 1345 | +{ | ||
| 1346 | + if (uid > 65535) | ||
| 1347 | + return 65534; | ||
| 1348 | + else | ||
| 1349 | + return uid; | ||
| 1350 | +} | ||
| 1351 | + | ||
| 1352 | +static inline int high2lowgid(int gid) | ||
| 1353 | +{ | ||
| 1354 | + if (gid > 65535) | ||
| 1355 | + return 65534; | ||
| 1356 | + else | ||
| 1357 | + return gid; | ||
| 1358 | +} | ||
| 1359 | + | ||
| 1360 | +static inline int low2highuid(int uid) | ||
| 1361 | +{ | ||
| 1362 | + if ((int16_t)uid == -1) | ||
| 1363 | + return -1; | ||
| 1364 | + else | ||
| 1365 | + return uid; | ||
| 1366 | +} | ||
| 1367 | + | ||
| 1368 | +static inline int low2highgid(int gid) | ||
| 1369 | +{ | ||
| 1370 | + if ((int16_t)gid == -1) | ||
| 1371 | + return -1; | ||
| 1372 | + else | ||
| 1373 | + return gid; | ||
| 1374 | +} | ||
| 1375 | + | ||
| 1376 | +#endif /* USE_UID16 */ | ||
| 1333 | 1377 | ||
| 1334 | void syscall_init(void) | 1378 | void syscall_init(void) |
| 1335 | { | 1379 | { |
| @@ -1472,9 +1516,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1472,9 +1516,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 1472 | case TARGET_NR_chmod: | 1516 | case TARGET_NR_chmod: |
| 1473 | ret = get_errno(chmod((const char *)arg1, arg2)); | 1517 | ret = get_errno(chmod((const char *)arg1, arg2)); |
| 1474 | break; | 1518 | break; |
| 1475 | - case TARGET_NR_lchown: | ||
| 1476 | - ret = get_errno(chown((const char *)arg1, arg2, arg3)); | ||
| 1477 | - break; | ||
| 1478 | #ifdef TARGET_NR_break | 1519 | #ifdef TARGET_NR_break |
| 1479 | case TARGET_NR_break: | 1520 | case TARGET_NR_break: |
| 1480 | goto unimplemented; | 1521 | goto unimplemented; |
| @@ -1495,12 +1536,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1495,12 +1536,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 1495 | case TARGET_NR_umount: | 1536 | case TARGET_NR_umount: |
| 1496 | ret = get_errno(umount((const char *)arg1)); | 1537 | ret = get_errno(umount((const char *)arg1)); |
| 1497 | break; | 1538 | break; |
| 1498 | - case TARGET_NR_setuid: | ||
| 1499 | - ret = get_errno(setuid(low2highuid(arg1))); | ||
| 1500 | - break; | ||
| 1501 | - case TARGET_NR_getuid: | ||
| 1502 | - ret = get_errno(getuid()); | ||
| 1503 | - break; | ||
| 1504 | case TARGET_NR_stime: | 1539 | case TARGET_NR_stime: |
| 1505 | { | 1540 | { |
| 1506 | int *time_ptr = (int *)arg1; | 1541 | int *time_ptr = (int *)arg1; |
| @@ -1596,20 +1631,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1596,20 +1631,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 1596 | case TARGET_NR_prof: | 1631 | case TARGET_NR_prof: |
| 1597 | goto unimplemented; | 1632 | goto unimplemented; |
| 1598 | #endif | 1633 | #endif |
| 1599 | - case TARGET_NR_setgid: | ||
| 1600 | - ret = get_errno(setgid(low2highgid(arg1))); | ||
| 1601 | - break; | ||
| 1602 | - case TARGET_NR_getgid: | ||
| 1603 | - ret = get_errno(getgid()); | ||
| 1604 | - break; | ||
| 1605 | case TARGET_NR_signal: | 1634 | case TARGET_NR_signal: |
| 1606 | goto unimplemented; | 1635 | goto unimplemented; |
| 1607 | - case TARGET_NR_geteuid: | ||
| 1608 | - ret = get_errno(geteuid()); | ||
| 1609 | - break; | ||
| 1610 | - case TARGET_NR_getegid: | ||
| 1611 | - ret = get_errno(getegid()); | ||
| 1612 | - break; | 1636 | + |
| 1613 | case TARGET_NR_acct: | 1637 | case TARGET_NR_acct: |
| 1614 | goto unimplemented; | 1638 | goto unimplemented; |
| 1615 | case TARGET_NR_umount2: | 1639 | case TARGET_NR_umount2: |
| @@ -1844,12 +1868,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1844,12 +1868,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 1844 | /* NOTE: ret is eax, so not transcoding must be done */ | 1868 | /* NOTE: ret is eax, so not transcoding must be done */ |
| 1845 | ret = do_rt_sigreturn(cpu_env); | 1869 | ret = do_rt_sigreturn(cpu_env); |
| 1846 | break; | 1870 | break; |
| 1847 | - case TARGET_NR_setreuid: | ||
| 1848 | - ret = get_errno(setreuid(arg1, arg2)); | ||
| 1849 | - break; | ||
| 1850 | - case TARGET_NR_setregid: | ||
| 1851 | - ret = get_errno(setregid(arg1, arg2)); | ||
| 1852 | - break; | ||
| 1853 | case TARGET_NR_sethostname: | 1871 | case TARGET_NR_sethostname: |
| 1854 | ret = get_errno(sethostname((const char *)arg1, arg2)); | 1872 | ret = get_errno(sethostname((const char *)arg1, arg2)); |
| 1855 | break; | 1873 | break; |
| @@ -1906,34 +1924,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1906,34 +1924,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 1906 | ret = get_errno(settimeofday(&tv, NULL)); | 1924 | ret = get_errno(settimeofday(&tv, NULL)); |
| 1907 | } | 1925 | } |
| 1908 | break; | 1926 | break; |
| 1909 | - case TARGET_NR_getgroups: | ||
| 1910 | - { | ||
| 1911 | - int gidsetsize = arg1; | ||
| 1912 | - uint16_t *target_grouplist = (void *)arg2; | ||
| 1913 | - gid_t *grouplist; | ||
| 1914 | - int i; | ||
| 1915 | - | ||
| 1916 | - grouplist = alloca(gidsetsize * sizeof(gid_t)); | ||
| 1917 | - ret = get_errno(getgroups(gidsetsize, grouplist)); | ||
| 1918 | - if (!is_error(ret)) { | ||
| 1919 | - for(i = 0;i < gidsetsize; i++) | ||
| 1920 | - target_grouplist[i] = tswap16(grouplist[i]); | ||
| 1921 | - } | ||
| 1922 | - } | ||
| 1923 | - break; | ||
| 1924 | - case TARGET_NR_setgroups: | ||
| 1925 | - { | ||
| 1926 | - int gidsetsize = arg1; | ||
| 1927 | - uint16_t *target_grouplist = (void *)arg2; | ||
| 1928 | - gid_t *grouplist; | ||
| 1929 | - int i; | ||
| 1930 | - | ||
| 1931 | - grouplist = alloca(gidsetsize * sizeof(gid_t)); | ||
| 1932 | - for(i = 0;i < gidsetsize; i++) | ||
| 1933 | - grouplist[i] = tswap16(target_grouplist[i]); | ||
| 1934 | - ret = get_errno(setgroups(gidsetsize, grouplist)); | ||
| 1935 | - } | ||
| 1936 | - break; | ||
| 1937 | case TARGET_NR_select: | 1927 | case TARGET_NR_select: |
| 1938 | { | 1928 | { |
| 1939 | struct target_sel_arg_struct *sel = (void *)arg1; | 1929 | 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, | @@ -2026,9 +2016,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 2026 | case TARGET_NR_fchmod: | 2016 | case TARGET_NR_fchmod: |
| 2027 | ret = get_errno(fchmod(arg1, arg2)); | 2017 | ret = get_errno(fchmod(arg1, arg2)); |
| 2028 | break; | 2018 | break; |
| 2029 | - case TARGET_NR_fchown: | ||
| 2030 | - ret = get_errno(fchown(arg1, arg2, arg3)); | ||
| 2031 | - break; | ||
| 2032 | case TARGET_NR_getpriority: | 2019 | case TARGET_NR_getpriority: |
| 2033 | ret = get_errno(getpriority(arg1, arg2)); | 2020 | ret = get_errno(getpriority(arg1, arg2)); |
| 2034 | break; | 2021 | break; |
| @@ -2121,10 +2108,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2121,10 +2108,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 2121 | struct target_stat *target_st = (void *)arg2; | 2108 | struct target_stat *target_st = (void *)arg2; |
| 2122 | target_st->st_dev = tswap16(st.st_dev); | 2109 | target_st->st_dev = tswap16(st.st_dev); |
| 2123 | target_st->st_ino = tswapl(st.st_ino); | 2110 | target_st->st_ino = tswapl(st.st_ino); |
| 2111 | +#if defined(TARGET_PPC) | ||
| 2112 | + target_st->st_mode = tswapl(st.st_mode); /* XXX: check this */ | ||
| 2113 | + target_st->st_uid = tswap32(st.st_uid); | ||
| 2114 | + target_st->st_gid = tswap32(st.st_gid); | ||
| 2115 | +#else | ||
| 2124 | target_st->st_mode = tswap16(st.st_mode); | 2116 | target_st->st_mode = tswap16(st.st_mode); |
| 2125 | - target_st->st_nlink = tswap16(st.st_nlink); | ||
| 2126 | target_st->st_uid = tswap16(st.st_uid); | 2117 | target_st->st_uid = tswap16(st.st_uid); |
| 2127 | target_st->st_gid = tswap16(st.st_gid); | 2118 | target_st->st_gid = tswap16(st.st_gid); |
| 2119 | +#endif | ||
| 2120 | + target_st->st_nlink = tswap16(st.st_nlink); | ||
| 2128 | target_st->st_rdev = tswap16(st.st_rdev); | 2121 | target_st->st_rdev = tswap16(st.st_rdev); |
| 2129 | target_st->st_size = tswapl(st.st_size); | 2122 | target_st->st_size = tswapl(st.st_size); |
| 2130 | target_st->st_blksize = tswapl(st.st_blksize); | 2123 | 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, | @@ -2230,12 +2223,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 2230 | break; | 2223 | break; |
| 2231 | case TARGET_NR_afs_syscall: | 2224 | case TARGET_NR_afs_syscall: |
| 2232 | goto unimplemented; | 2225 | goto unimplemented; |
| 2233 | - case TARGET_NR_setfsuid: | ||
| 2234 | - ret = get_errno(setfsuid(arg1)); | ||
| 2235 | - break; | ||
| 2236 | - case TARGET_NR_setfsgid: | ||
| 2237 | - ret = get_errno(setfsgid(arg1)); | ||
| 2238 | - break; | ||
| 2239 | case TARGET_NR__llseek: | 2226 | case TARGET_NR__llseek: |
| 2240 | { | 2227 | { |
| 2241 | int64_t res; | 2228 | int64_t res; |
| @@ -2465,52 +2452,13 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2465,52 +2452,13 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 2465 | } | 2452 | } |
| 2466 | } | 2453 | } |
| 2467 | break; | 2454 | break; |
| 2468 | -#ifdef TARGET_NR_setresuid | ||
| 2469 | - case TARGET_NR_setresuid: | ||
| 2470 | - ret = get_errno(setresuid(low2highuid(arg1), | ||
| 2471 | - low2highuid(arg2), | ||
| 2472 | - low2highuid(arg3))); | ||
| 2473 | - break; | ||
| 2474 | -#endif | ||
| 2475 | -#ifdef TARGET_NR_getresuid | ||
| 2476 | - case TARGET_NR_getresuid: | ||
| 2477 | - { | ||
| 2478 | - int ruid, euid, suid; | ||
| 2479 | - ret = get_errno(getresuid(&ruid, &euid, &suid)); | ||
| 2480 | - if (!is_error(ret)) { | ||
| 2481 | - *(uint16_t *)arg1 = tswap16(high2lowuid(ruid)); | ||
| 2482 | - *(uint16_t *)arg2 = tswap16(high2lowuid(euid)); | ||
| 2483 | - *(uint16_t *)arg3 = tswap16(high2lowuid(suid)); | ||
| 2484 | - } | ||
| 2485 | - } | ||
| 2486 | - break; | ||
| 2487 | -#endif | ||
| 2488 | -#ifdef TARGET_NR_getresgid | ||
| 2489 | - case TARGET_NR_setresgid: | ||
| 2490 | - ret = get_errno(setresgid(low2highgid(arg1), | ||
| 2491 | - low2highgid(arg2), | ||
| 2492 | - low2highgid(arg3))); | ||
| 2493 | - break; | ||
| 2494 | -#endif | ||
| 2495 | -#ifdef TARGET_NR_getresgid | ||
| 2496 | - case TARGET_NR_getresgid: | ||
| 2497 | - { | ||
| 2498 | - int rgid, egid, sgid; | ||
| 2499 | - ret = get_errno(getresgid(&rgid, &egid, &sgid)); | ||
| 2500 | - if (!is_error(ret)) { | ||
| 2501 | - *(uint16_t *)arg1 = high2lowgid(tswap16(rgid)); | ||
| 2502 | - *(uint16_t *)arg2 = high2lowgid(tswap16(egid)); | ||
| 2503 | - *(uint16_t *)arg3 = high2lowgid(tswap16(sgid)); | ||
| 2504 | - } | ||
| 2505 | - } | ||
| 2506 | - break; | ||
| 2507 | -#endif | ||
| 2508 | case TARGET_NR_query_module: | 2455 | case TARGET_NR_query_module: |
| 2509 | goto unimplemented; | 2456 | goto unimplemented; |
| 2510 | case TARGET_NR_nfsservctl: | 2457 | case TARGET_NR_nfsservctl: |
| 2511 | goto unimplemented; | 2458 | goto unimplemented; |
| 2512 | case TARGET_NR_prctl: | 2459 | case TARGET_NR_prctl: |
| 2513 | goto unimplemented; | 2460 | goto unimplemented; |
| 2461 | +#ifdef TARGET_NR_pread | ||
| 2514 | case TARGET_NR_pread: | 2462 | case TARGET_NR_pread: |
| 2515 | page_unprotect_range((void *)arg2, arg3); | 2463 | page_unprotect_range((void *)arg2, arg3); |
| 2516 | ret = get_errno(pread(arg1, (void *)arg2, arg3, arg4)); | 2464 | 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, | @@ -2518,9 +2466,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 2518 | case TARGET_NR_pwrite: | 2466 | case TARGET_NR_pwrite: |
| 2519 | ret = get_errno(pwrite(arg1, (void *)arg2, arg3, arg4)); | 2467 | ret = get_errno(pwrite(arg1, (void *)arg2, arg3, arg4)); |
| 2520 | break; | 2468 | break; |
| 2521 | - case TARGET_NR_chown: | ||
| 2522 | - ret = get_errno(chown((const char *)arg1, arg2, arg3)); | ||
| 2523 | - break; | 2469 | +#endif |
| 2524 | case TARGET_NR_getcwd: | 2470 | case TARGET_NR_getcwd: |
| 2525 | ret = get_errno(sys_getcwd1((char *)arg1, arg2)); | 2471 | ret = get_errno(sys_getcwd1((char *)arg1, arg2)); |
| 2526 | break; | 2472 | break; |
| @@ -2594,6 +2540,116 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2594,6 +2540,116 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 2594 | } | 2540 | } |
| 2595 | break; | 2541 | break; |
| 2596 | 2542 | ||
| 2543 | +#ifdef USE_UID16 | ||
| 2544 | + case TARGET_NR_lchown: | ||
| 2545 | + ret = get_errno(lchown((const char *)arg1, low2highuid(arg2), low2highgid(arg3))); | ||
| 2546 | + break; | ||
| 2547 | + case TARGET_NR_getuid: | ||
| 2548 | + ret = get_errno(high2lowuid(getuid())); | ||
| 2549 | + break; | ||
| 2550 | + case TARGET_NR_getgid: | ||
| 2551 | + ret = get_errno(high2lowgid(getgid())); | ||
| 2552 | + break; | ||
| 2553 | + case TARGET_NR_geteuid: | ||
| 2554 | + ret = get_errno(high2lowuid(geteuid())); | ||
| 2555 | + break; | ||
| 2556 | + case TARGET_NR_getegid: | ||
| 2557 | + ret = get_errno(high2lowgid(getegid())); | ||
| 2558 | + break; | ||
| 2559 | + case TARGET_NR_setreuid: | ||
| 2560 | + ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2))); | ||
| 2561 | + break; | ||
| 2562 | + case TARGET_NR_setregid: | ||
| 2563 | + ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2))); | ||
| 2564 | + break; | ||
| 2565 | + case TARGET_NR_getgroups: | ||
| 2566 | + { | ||
| 2567 | + int gidsetsize = arg1; | ||
| 2568 | + uint16_t *target_grouplist = (void *)arg2; | ||
| 2569 | + gid_t *grouplist; | ||
| 2570 | + int i; | ||
| 2571 | + | ||
| 2572 | + grouplist = alloca(gidsetsize * sizeof(gid_t)); | ||
| 2573 | + ret = get_errno(getgroups(gidsetsize, grouplist)); | ||
| 2574 | + if (!is_error(ret)) { | ||
| 2575 | + for(i = 0;i < gidsetsize; i++) | ||
| 2576 | + target_grouplist[i] = tswap16(grouplist[i]); | ||
| 2577 | + } | ||
| 2578 | + } | ||
| 2579 | + break; | ||
| 2580 | + case TARGET_NR_setgroups: | ||
| 2581 | + { | ||
| 2582 | + int gidsetsize = arg1; | ||
| 2583 | + uint16_t *target_grouplist = (void *)arg2; | ||
| 2584 | + gid_t *grouplist; | ||
| 2585 | + int i; | ||
| 2586 | + | ||
| 2587 | + grouplist = alloca(gidsetsize * sizeof(gid_t)); | ||
| 2588 | + for(i = 0;i < gidsetsize; i++) | ||
| 2589 | + grouplist[i] = tswap16(target_grouplist[i]); | ||
| 2590 | + ret = get_errno(setgroups(gidsetsize, grouplist)); | ||
| 2591 | + } | ||
| 2592 | + break; | ||
| 2593 | + case TARGET_NR_fchown: | ||
| 2594 | + ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3))); | ||
| 2595 | + break; | ||
| 2596 | +#ifdef TARGET_NR_setresuid | ||
| 2597 | + case TARGET_NR_setresuid: | ||
| 2598 | + ret = get_errno(setresuid(low2highuid(arg1), | ||
| 2599 | + low2highuid(arg2), | ||
| 2600 | + low2highuid(arg3))); | ||
| 2601 | + break; | ||
| 2602 | +#endif | ||
| 2603 | +#ifdef TARGET_NR_getresuid | ||
| 2604 | + case TARGET_NR_getresuid: | ||
| 2605 | + { | ||
| 2606 | + int ruid, euid, suid; | ||
| 2607 | + ret = get_errno(getresuid(&ruid, &euid, &suid)); | ||
| 2608 | + if (!is_error(ret)) { | ||
| 2609 | + *(uint16_t *)arg1 = tswap16(high2lowuid(ruid)); | ||
| 2610 | + *(uint16_t *)arg2 = tswap16(high2lowuid(euid)); | ||
| 2611 | + *(uint16_t *)arg3 = tswap16(high2lowuid(suid)); | ||
| 2612 | + } | ||
| 2613 | + } | ||
| 2614 | + break; | ||
| 2615 | +#endif | ||
| 2616 | +#ifdef TARGET_NR_getresgid | ||
| 2617 | + case TARGET_NR_setresgid: | ||
| 2618 | + ret = get_errno(setresgid(low2highgid(arg1), | ||
| 2619 | + low2highgid(arg2), | ||
| 2620 | + low2highgid(arg3))); | ||
| 2621 | + break; | ||
| 2622 | +#endif | ||
| 2623 | +#ifdef TARGET_NR_getresgid | ||
| 2624 | + case TARGET_NR_getresgid: | ||
| 2625 | + { | ||
| 2626 | + int rgid, egid, sgid; | ||
| 2627 | + ret = get_errno(getresgid(&rgid, &egid, &sgid)); | ||
| 2628 | + if (!is_error(ret)) { | ||
| 2629 | + *(uint16_t *)arg1 = tswap16(high2lowgid(rgid)); | ||
| 2630 | + *(uint16_t *)arg2 = tswap16(high2lowgid(egid)); | ||
| 2631 | + *(uint16_t *)arg3 = tswap16(high2lowgid(sgid)); | ||
| 2632 | + } | ||
| 2633 | + } | ||
| 2634 | + break; | ||
| 2635 | +#endif | ||
| 2636 | + case TARGET_NR_chown: | ||
| 2637 | + ret = get_errno(chown((const char *)arg1, low2highuid(arg2), low2highgid(arg3))); | ||
| 2638 | + break; | ||
| 2639 | + case TARGET_NR_setuid: | ||
| 2640 | + ret = get_errno(setuid(low2highuid(arg1))); | ||
| 2641 | + break; | ||
| 2642 | + case TARGET_NR_setgid: | ||
| 2643 | + ret = get_errno(setgid(low2highgid(arg1))); | ||
| 2644 | + break; | ||
| 2645 | + case TARGET_NR_setfsuid: | ||
| 2646 | + ret = get_errno(setfsuid(arg1)); | ||
| 2647 | + break; | ||
| 2648 | + case TARGET_NR_setfsgid: | ||
| 2649 | + ret = get_errno(setfsgid(arg1)); | ||
| 2650 | + break; | ||
| 2651 | +#endif /* USE_UID16 */ | ||
| 2652 | + | ||
| 2597 | case TARGET_NR_lchown32: | 2653 | case TARGET_NR_lchown32: |
| 2598 | ret = get_errno(lchown((const char *)arg1, arg2, arg3)); | 2654 | ret = get_errno(lchown((const char *)arg1, arg2, arg3)); |
| 2599 | break; | 2655 | break; |
| @@ -2665,6 +2721,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2665,6 +2721,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 2665 | case TARGET_NR_setfsgid32: | 2721 | case TARGET_NR_setfsgid32: |
| 2666 | ret = get_errno(setfsgid(arg1)); | 2722 | ret = get_errno(setfsgid(arg1)); |
| 2667 | break; | 2723 | break; |
| 2724 | + | ||
| 2668 | case TARGET_NR_pivot_root: | 2725 | case TARGET_NR_pivot_root: |
| 2669 | goto unimplemented; | 2726 | goto unimplemented; |
| 2670 | case TARGET_NR_mincore: | 2727 | case TARGET_NR_mincore: |
linux-user/syscall_defs.h
| @@ -279,7 +279,7 @@ struct target_sigaction; | @@ -279,7 +279,7 @@ struct target_sigaction; | ||
| 279 | int do_sigaction(int sig, const struct target_sigaction *act, | 279 | int do_sigaction(int sig, const struct target_sigaction *act, |
| 280 | struct target_sigaction *oact); | 280 | struct target_sigaction *oact); |
| 281 | 281 | ||
| 282 | -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) | 282 | +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) |
| 283 | 283 | ||
| 284 | #define TARGET_SA_NOCLDSTOP 0x00000001 | 284 | #define TARGET_SA_NOCLDSTOP 0x00000001 |
| 285 | #define TARGET_SA_NOCLDWAIT 0x00000002 /* not supported yet */ | 285 | #define TARGET_SA_NOCLDWAIT 0x00000002 /* not supported yet */ |
| @@ -664,7 +664,7 @@ struct target_pollfd { | @@ -664,7 +664,7 @@ struct target_pollfd { | ||
| 664 | #define TARGET_HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */ | 664 | #define TARGET_HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */ |
| 665 | 665 | ||
| 666 | 666 | ||
| 667 | -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) | 667 | +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) |
| 668 | 668 | ||
| 669 | /* 0x54 is just a magic number to make these relatively unique ('T') */ | 669 | /* 0x54 is just a magic number to make these relatively unique ('T') */ |
| 670 | 670 | ||
| @@ -891,6 +891,9 @@ struct target_termios { | @@ -891,6 +891,9 @@ struct target_termios { | ||
| 891 | #define TARGET_MAP_LOCKED 0x2000 /* pages are locked */ | 891 | #define TARGET_MAP_LOCKED 0x2000 /* pages are locked */ |
| 892 | #define TARGET_MAP_NORESERVE 0x4000 /* don't check for reservations */ | 892 | #define TARGET_MAP_NORESERVE 0x4000 /* don't check for reservations */ |
| 893 | 893 | ||
| 894 | +#endif /* defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) */ | ||
| 895 | + | ||
| 896 | +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) | ||
| 894 | struct target_stat { | 897 | struct target_stat { |
| 895 | unsigned short st_dev; | 898 | unsigned short st_dev; |
| 896 | unsigned short __pad1; | 899 | unsigned short __pad1; |
| @@ -951,7 +954,62 @@ struct target_stat64 { | @@ -951,7 +954,62 @@ struct target_stat64 { | ||
| 951 | unsigned long long st_ino; | 954 | unsigned long long st_ino; |
| 952 | } __attribute__((packed)); | 955 | } __attribute__((packed)); |
| 953 | 956 | ||
| 954 | -#endif /* defined(TARGET_I386) || defined(TARGET_ARM) */ | 957 | +#elif defined(TARGET_PPC) |
| 958 | + | ||
| 959 | +struct target_stat { | ||
| 960 | + unsigned short st_dev; | ||
| 961 | + target_ulong st_ino; | ||
| 962 | + unsigned int st_mode; | ||
| 963 | + unsigned short st_nlink; | ||
| 964 | + unsigned int st_uid; | ||
| 965 | + unsigned int st_gid; | ||
| 966 | + unsigned short st_rdev; | ||
| 967 | + target_ulong st_size; | ||
| 968 | + target_ulong st_blksize; | ||
| 969 | + target_ulong st_blocks; | ||
| 970 | + target_ulong target_st_atime; | ||
| 971 | + target_ulong __unused1; | ||
| 972 | + target_ulong target_st_mtime; | ||
| 973 | + target_ulong __unused2; | ||
| 974 | + target_ulong target_st_ctime; | ||
| 975 | + target_ulong __unused3; | ||
| 976 | + target_ulong __unused4; | ||
| 977 | + target_ulong __unused5; | ||
| 978 | +}; | ||
| 979 | + | ||
| 980 | +struct target_stat64 { | ||
| 981 | + unsigned long long st_dev; | ||
| 982 | + | ||
| 983 | + unsigned long long st_ino; | ||
| 984 | + | ||
| 985 | + unsigned int st_mode; | ||
| 986 | + unsigned int st_nlink; | ||
| 987 | + | ||
| 988 | + unsigned int st_uid; | ||
| 989 | + unsigned int st_gid; | ||
| 990 | + | ||
| 991 | + unsigned long long st_rdev; | ||
| 992 | + unsigned short int __pad2; | ||
| 993 | + | ||
| 994 | + long long st_size; | ||
| 995 | + target_ulong st_blksize; | ||
| 996 | + | ||
| 997 | + long long st_blocks; /* Number 512-byte blocks allocated. */ | ||
| 998 | + | ||
| 999 | + target_ulong target_st_atime; | ||
| 1000 | + target_ulong target_st_atime_nsec; | ||
| 1001 | + | ||
| 1002 | + target_ulong target_st_mtime; | ||
| 1003 | + target_ulong target_st_mtime_nsec; | ||
| 1004 | + | ||
| 1005 | + target_ulong target_st_ctime; | ||
| 1006 | + target_ulong target_st_ctime_nsec; | ||
| 1007 | + | ||
| 1008 | + target_ulong __unused4; | ||
| 1009 | + target_ulong __unused5; | ||
| 1010 | +}; | ||
| 1011 | + | ||
| 1012 | +#endif /* defined(TARGET_PPC) */ | ||
| 955 | 1013 | ||
| 956 | #define TARGET_F_DUPFD 0 /* dup */ | 1014 | #define TARGET_F_DUPFD 0 /* dup */ |
| 957 | #define TARGET_F_GETFD 1 /* get close_on_exec */ | 1015 | #define TARGET_F_GETFD 1 /* get close_on_exec */ |