diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-06-15 19:56:46 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-06-15 19:56:46 +0000 |
commit | 2ab83ea7849c2a113ab3ebf0c973435117ddf2d0 (patch) | |
tree | fc3fb1aaff125a501793b764ccaf892f1f312621 /linux-user/syscall.c | |
parent | 24374901004c774e8b932a3526bda6c627942a88 (diff) |
automatic ioctl number conversion - minimum ARM fork() support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@240 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r-- | linux-user/syscall.c | 72 |
1 files changed, 54 insertions, 18 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 9b02d5eaf4..b226429103 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -68,11 +68,6 @@ #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); - #define __NR_sys_uname __NR_uname #define __NR_sys_getcwd1 __NR_getcwd #define __NR_sys_statfs __NR_statfs @@ -702,8 +697,8 @@ enum { #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]; @@ -715,7 +710,7 @@ typedef struct IOCTLEntry { #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" @@ -970,7 +965,7 @@ static bitmask_transtbl mmap_flags_tbl[] = { { 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; @@ -1087,28 +1082,28 @@ int do_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount 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; @@ -1117,10 +1112,21 @@ int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) 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); @@ -1136,8 +1142,6 @@ int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) return ret; } -#endif - static long do_fcntl(int fd, int cmd, unsigned long arg) { struct flock fl; @@ -1188,11 +1192,43 @@ static long do_fcntl(int fd, int cmd, unsigned long arg) 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, |