#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
-void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
-void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
-long do_sigreturn(CPUX86State *env);
-long do_rt_sigreturn(CPUX86State *env);
+
+#if defined(__powerpc__)
+#undef __syscall_nr
+#undef __sc_loadargs_0
+#undef __sc_loadargs_1
+#undef __sc_loadargs_2
+#undef __sc_loadargs_3
+#undef __sc_loadargs_4
+#undef __sc_loadargs_5
+#undef __sc_asm_input_0
+#undef __sc_asm_input_1
+#undef __sc_asm_input_2
+#undef __sc_asm_input_3
+#undef __sc_asm_input_4
+#undef __sc_asm_input_5
+#undef _syscall0
+#undef _syscall1
+#undef _syscall2
+#undef _syscall3
+#undef _syscall4
+#undef _syscall5
+
+/* need to redefine syscalls as Linux kernel defines are incorrect for
+ the clobber list */
+/* On powerpc a system call basically clobbers the same registers like a
+ * function call, with the exception of LR (which is needed for the
+ * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
+ * an error return status).
+ */
+
+#define __syscall_nr(nr, type, name, args...) \
+ unsigned long __sc_ret, __sc_err; \
+ { \
+ register unsigned long __sc_0 __asm__ ("r0"); \
+ register unsigned long __sc_3 __asm__ ("r3"); \
+ register unsigned long __sc_4 __asm__ ("r4"); \
+ register unsigned long __sc_5 __asm__ ("r5"); \
+ register unsigned long __sc_6 __asm__ ("r6"); \
+ register unsigned long __sc_7 __asm__ ("r7"); \
+ \
+ __sc_loadargs_##nr(name, args); \
+ __asm__ __volatile__ \
+ ("sc \n\t" \
+ "mfcr %0 " \
+ : "=&r" (__sc_0), \
+ "=&r" (__sc_3), "=&r" (__sc_4), \
+ "=&r" (__sc_5), "=&r" (__sc_6), \
+ "=&r" (__sc_7) \
+ : __sc_asm_input_##nr \
+ : "cr0", "ctr", "memory", \
+ "r8", "r9", "r10","r11", "r12"); \
+ __sc_ret = __sc_3; \
+ __sc_err = __sc_0; \
+ } \
+ if (__sc_err & 0x10000000) \
+ { \
+ errno = __sc_ret; \
+ __sc_ret = -1; \
+ } \
+ return (type) __sc_ret
+
+#define __sc_loadargs_0(name, dummy...) \
+ __sc_0 = __NR_##name
+#define __sc_loadargs_1(name, arg1) \
+ __sc_loadargs_0(name); \
+ __sc_3 = (unsigned long) (arg1)
+#define __sc_loadargs_2(name, arg1, arg2) \
+ __sc_loadargs_1(name, arg1); \
+ __sc_4 = (unsigned long) (arg2)
+#define __sc_loadargs_3(name, arg1, arg2, arg3) \
+ __sc_loadargs_2(name, arg1, arg2); \
+ __sc_5 = (unsigned long) (arg3)
+#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4) \
+ __sc_loadargs_3(name, arg1, arg2, arg3); \
+ __sc_6 = (unsigned long) (arg4)
+#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5) \
+ __sc_loadargs_4(name, arg1, arg2, arg3, arg4); \
+ __sc_7 = (unsigned long) (arg5)
+
+#define __sc_asm_input_0 "0" (__sc_0)
+#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3)
+#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4)
+#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5)
+#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6)
+#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7)
+
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+ __syscall_nr(0, type, name); \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
+{ \
+ __syscall_nr(1, type, name, arg1); \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1, type2 arg2) \
+{ \
+ __syscall_nr(2, type, name, arg1, arg2); \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1, type2 arg2, type3 arg3) \
+{ \
+ __syscall_nr(3, type, name, arg1, arg2, arg3); \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+ __syscall_nr(4, type, name, arg1, arg2, arg3, arg4); \
+}
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
+{ \
+ __syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5); \
+}
+#endif
#define __NR_sys_uname __NR_uname
#define __NR_sys_getcwd1 __NR_getcwd
#endif
}
+#if defined(__alpha__)
+#define HOST_HZ 1024
+#else
+#define HOST_HZ 100
+#endif
+
+static inline long host_to_target_clock_t(long ticks)
+{
+#if HOST_HZ == TARGET_HZ
+ return ticks;
+#else
+ return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
+#endif
+}
+
static inline void host_to_target_rusage(struct target_rusage *target_rusage,
const struct rusage *rusage)
{
#undef STRUCT_SPECIAL
typedef struct IOCTLEntry {
- int target_cmd;
- int host_cmd;
+ unsigned int target_cmd;
+ unsigned int host_cmd;
const char *name;
int access;
const argtype arg_type[5];
#define MAX_STRUCT_SIZE 4096
-const IOCTLEntry ioctl_entries[] = {
+IOCTLEntry ioctl_entries[] = {
#define IOCTL(cmd, access, types...) \
{ TARGET_ ## cmd, cmd, #cmd, access, { types } },
#include "ioctls.h"
{ 0, 0, 0, 0 }
};
-#ifdef TARGET_I386
+#if defined(TARGET_I386)
/* NOTE: there is really one LDT for all the threads */
uint8_t *ldt_table;
return ret;
}
+#endif /* defined(TARGET_I386) */
+
/* this stack is the equivalent of the kernel stack associated with a
thread/process */
#define NEW_STACK_SIZE 8192
static int clone_func(void *arg)
{
- CPUX86State *env = arg;
+ CPUState *env = arg;
cpu_loop(env);
/* never exits */
return 0;
}
-int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp)
+int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
{
int ret;
TaskState *ts;
uint8_t *new_stack;
- CPUX86State *new_env;
+ CPUState *new_env;
if (flags & CLONE_VM) {
- if (!newsp)
- newsp = env->regs[R_ESP];
ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
memset(ts, 0, sizeof(TaskState));
new_stack = ts->stack;
ts->next = first_task_state;
first_task_state = ts;
/* we create a new CPU instance. */
- new_env = cpu_x86_init();
- memcpy(new_env, env, sizeof(CPUX86State));
+ new_env = cpu_init();
+ memcpy(new_env, env, sizeof(CPUState));
+#if defined(TARGET_I386)
+ if (!newsp)
+ newsp = env->regs[R_ESP];
new_env->regs[R_ESP] = newsp;
new_env->regs[R_EAX] = 0;
+#elif defined(TARGET_ARM)
+ if (!newsp)
+ newsp = env->regs[13];
+ new_env->regs[13] = newsp;
+ new_env->regs[0] = 0;
+#else
+#error unsupported target CPU
+#endif
new_env->opaque = ts;
#ifdef __ia64__
ret = clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
return ret;
}
-#endif
-
static long do_fcntl(int fd, int cmd, unsigned long arg)
{
struct flock fl;
void syscall_init(void)
{
+ IOCTLEntry *ie;
+ const argtype *arg_type;
+ int size;
+
#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
#include "syscall_types.h"
#undef STRUCT
#undef STRUCT_SPECIAL
+
+ /* we patch the ioctl size if necessary. We rely on the fact that
+ no ioctl has all the bits at '1' in the size field */
+ ie = ioctl_entries;
+ while (ie->target_cmd != 0) {
+ if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
+ TARGET_IOC_SIZEMASK) {
+ arg_type = ie->arg_type;
+ if (arg_type[0] != TYPE_PTR) {
+ fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
+ ie->target_cmd);
+ exit(1);
+ }
+ arg_type++;
+ size = thunk_type_size(arg_type, 0);
+ ie->target_cmd = (ie->target_cmd &
+ ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
+ (size << TARGET_IOC_SIZESHIFT);
+ }
+ /* automatic consistency check if same arch */
+#if defined(__i386__) && defined(TARGET_I386)
+ if (ie->target_cmd != ie->host_cmd) {
+ fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n",
+ ie->target_cmd, ie->host_cmd);
+ }
+#endif
+ ie++;
+ }
}
long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
struct tms tms;
ret = get_errno(times(&tms));
if (tmsp) {
- tmsp->tms_utime = tswapl(tms.tms_utime);
- tmsp->tms_stime = tswapl(tms.tms_stime);
- tmsp->tms_cutime = tswapl(tms.tms_cutime);
- tmsp->tms_cstime = tswapl(tms.tms_cstime);
+ tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
+ tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
+ tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
+ tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
}
+ if (!is_error(ret))
+ ret = host_to_target_clock_t(ret);
}
break;
case TARGET_NR_prof:
}
break;
case TARGET_NR_select:
- goto unimplemented;
+ {
+ struct target_sel_arg_struct *sel = (void *)arg1;
+ sel->n = tswapl(sel->n);
+ sel->inp = tswapl(sel->inp);
+ sel->outp = tswapl(sel->outp);
+ sel->exp = tswapl(sel->exp);
+ sel->tvp = tswapl(sel->tvp);
+ ret = do_select(sel->n, (void *)sel->inp, (void *)sel->outp,
+ (void *)sel->exp, (void *)sel->tvp);
+ }
+ break;
case TARGET_NR_symlink:
ret = get_errno(symlink((const char *)arg1, (const char *)arg2));
break;
goto unimplemented;
case TARGET_NR_readdir:
goto unimplemented;
-#ifdef TARGET_I386
case TARGET_NR_mmap:
+#if defined(TARGET_I386) || defined(TARGET_ARM)
{
uint32_t v1, v2, v3, v4, v5, v6, *vptr;
vptr = (uint32_t *)arg1;
target_to_host_bitmask(v4, mmap_flags_tbl),
v5, v6));
}
- break;
-#endif
-#ifdef TARGET_I386
- case TARGET_NR_mmap2:
#else
- case TARGET_NR_mmap:
+ ret = get_errno(target_mmap(arg1, arg2, arg3,
+ target_to_host_bitmask(arg4, mmap_flags_tbl),
+ arg5,
+ arg6));
#endif
+ break;
+ case TARGET_NR_mmap2:
ret = get_errno(target_mmap(arg1, arg2, arg3,
target_to_host_bitmask(arg4, mmap_flags_tbl),
arg5,