summaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-06-15 19:56:46 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-06-15 19:56:46 +0000
commit2ab83ea7849c2a113ab3ebf0c973435117ddf2d0 (patch)
treefc3fb1aaff125a501793b764ccaf892f1f312621 /linux-user
parent24374901004c774e8b932a3526bda6c627942a88 (diff)
downloadqemu-2ab83ea7849c2a113ab3ebf0c973435117ddf2d0.tar.gz
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')
-rw-r--r--linux-user/syscall.c72
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,