Commit 2ab83ea7849c2a113ab3ebf0c973435117ddf2d0
1 parent
24374901
automatic ioctl number conversion - minimum ARM fork() support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@240 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
54 additions
and
18 deletions
linux-user/syscall.c
| @@ -68,11 +68,6 @@ | @@ -68,11 +68,6 @@ | ||
| 68 | #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) | 68 | #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) |
| 69 | #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) | 69 | #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) |
| 70 | 70 | ||
| 71 | -void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); | ||
| 72 | -void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); | ||
| 73 | -long do_sigreturn(CPUX86State *env); | ||
| 74 | -long do_rt_sigreturn(CPUX86State *env); | ||
| 75 | - | ||
| 76 | #define __NR_sys_uname __NR_uname | 71 | #define __NR_sys_uname __NR_uname |
| 77 | #define __NR_sys_getcwd1 __NR_getcwd | 72 | #define __NR_sys_getcwd1 __NR_getcwd |
| 78 | #define __NR_sys_statfs __NR_statfs | 73 | #define __NR_sys_statfs __NR_statfs |
| @@ -702,8 +697,8 @@ enum { | @@ -702,8 +697,8 @@ enum { | ||
| 702 | #undef STRUCT_SPECIAL | 697 | #undef STRUCT_SPECIAL |
| 703 | 698 | ||
| 704 | typedef struct IOCTLEntry { | 699 | typedef struct IOCTLEntry { |
| 705 | - int target_cmd; | ||
| 706 | - int host_cmd; | 700 | + unsigned int target_cmd; |
| 701 | + unsigned int host_cmd; | ||
| 707 | const char *name; | 702 | const char *name; |
| 708 | int access; | 703 | int access; |
| 709 | const argtype arg_type[5]; | 704 | const argtype arg_type[5]; |
| @@ -715,7 +710,7 @@ typedef struct IOCTLEntry { | @@ -715,7 +710,7 @@ typedef struct IOCTLEntry { | ||
| 715 | 710 | ||
| 716 | #define MAX_STRUCT_SIZE 4096 | 711 | #define MAX_STRUCT_SIZE 4096 |
| 717 | 712 | ||
| 718 | -const IOCTLEntry ioctl_entries[] = { | 713 | +IOCTLEntry ioctl_entries[] = { |
| 719 | #define IOCTL(cmd, access, types...) \ | 714 | #define IOCTL(cmd, access, types...) \ |
| 720 | { TARGET_ ## cmd, cmd, #cmd, access, { types } }, | 715 | { TARGET_ ## cmd, cmd, #cmd, access, { types } }, |
| 721 | #include "ioctls.h" | 716 | #include "ioctls.h" |
| @@ -970,7 +965,7 @@ static bitmask_transtbl mmap_flags_tbl[] = { | @@ -970,7 +965,7 @@ static bitmask_transtbl mmap_flags_tbl[] = { | ||
| 970 | { 0, 0, 0, 0 } | 965 | { 0, 0, 0, 0 } |
| 971 | }; | 966 | }; |
| 972 | 967 | ||
| 973 | -#ifdef TARGET_I386 | 968 | +#if defined(TARGET_I386) |
| 974 | 969 | ||
| 975 | /* NOTE: there is really one LDT for all the threads */ | 970 | /* NOTE: there is really one LDT for all the threads */ |
| 976 | uint8_t *ldt_table; | 971 | uint8_t *ldt_table; |
| @@ -1087,28 +1082,28 @@ int do_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount | @@ -1087,28 +1082,28 @@ int do_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount | ||
| 1087 | return ret; | 1082 | return ret; |
| 1088 | } | 1083 | } |
| 1089 | 1084 | ||
| 1085 | +#endif /* defined(TARGET_I386) */ | ||
| 1086 | + | ||
| 1090 | /* this stack is the equivalent of the kernel stack associated with a | 1087 | /* this stack is the equivalent of the kernel stack associated with a |
| 1091 | thread/process */ | 1088 | thread/process */ |
| 1092 | #define NEW_STACK_SIZE 8192 | 1089 | #define NEW_STACK_SIZE 8192 |
| 1093 | 1090 | ||
| 1094 | static int clone_func(void *arg) | 1091 | static int clone_func(void *arg) |
| 1095 | { | 1092 | { |
| 1096 | - CPUX86State *env = arg; | 1093 | + CPUState *env = arg; |
| 1097 | cpu_loop(env); | 1094 | cpu_loop(env); |
| 1098 | /* never exits */ | 1095 | /* never exits */ |
| 1099 | return 0; | 1096 | return 0; |
| 1100 | } | 1097 | } |
| 1101 | 1098 | ||
| 1102 | -int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) | 1099 | +int do_fork(CPUState *env, unsigned int flags, unsigned long newsp) |
| 1103 | { | 1100 | { |
| 1104 | int ret; | 1101 | int ret; |
| 1105 | TaskState *ts; | 1102 | TaskState *ts; |
| 1106 | uint8_t *new_stack; | 1103 | uint8_t *new_stack; |
| 1107 | - CPUX86State *new_env; | 1104 | + CPUState *new_env; |
| 1108 | 1105 | ||
| 1109 | if (flags & CLONE_VM) { | 1106 | if (flags & CLONE_VM) { |
| 1110 | - if (!newsp) | ||
| 1111 | - newsp = env->regs[R_ESP]; | ||
| 1112 | ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); | 1107 | ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); |
| 1113 | memset(ts, 0, sizeof(TaskState)); | 1108 | memset(ts, 0, sizeof(TaskState)); |
| 1114 | new_stack = ts->stack; | 1109 | new_stack = ts->stack; |
| @@ -1117,10 +1112,21 @@ int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) | @@ -1117,10 +1112,21 @@ int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) | ||
| 1117 | ts->next = first_task_state; | 1112 | ts->next = first_task_state; |
| 1118 | first_task_state = ts; | 1113 | first_task_state = ts; |
| 1119 | /* we create a new CPU instance. */ | 1114 | /* we create a new CPU instance. */ |
| 1120 | - new_env = cpu_x86_init(); | ||
| 1121 | - memcpy(new_env, env, sizeof(CPUX86State)); | 1115 | + new_env = cpu_init(); |
| 1116 | + memcpy(new_env, env, sizeof(CPUState)); | ||
| 1117 | +#if defined(TARGET_I386) | ||
| 1118 | + if (!newsp) | ||
| 1119 | + newsp = env->regs[R_ESP]; | ||
| 1122 | new_env->regs[R_ESP] = newsp; | 1120 | new_env->regs[R_ESP] = newsp; |
| 1123 | new_env->regs[R_EAX] = 0; | 1121 | new_env->regs[R_EAX] = 0; |
| 1122 | +#elif defined(TARGET_ARM) | ||
| 1123 | + if (!newsp) | ||
| 1124 | + newsp = env->regs[13]; | ||
| 1125 | + new_env->regs[13] = newsp; | ||
| 1126 | + new_env->regs[0] = 0; | ||
| 1127 | +#else | ||
| 1128 | +#error unsupported target CPU | ||
| 1129 | +#endif | ||
| 1124 | new_env->opaque = ts; | 1130 | new_env->opaque = ts; |
| 1125 | #ifdef __ia64__ | 1131 | #ifdef __ia64__ |
| 1126 | ret = clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); | 1132 | 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) | @@ -1136,8 +1142,6 @@ int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) | ||
| 1136 | return ret; | 1142 | return ret; |
| 1137 | } | 1143 | } |
| 1138 | 1144 | ||
| 1139 | -#endif | ||
| 1140 | - | ||
| 1141 | static long do_fcntl(int fd, int cmd, unsigned long arg) | 1145 | static long do_fcntl(int fd, int cmd, unsigned long arg) |
| 1142 | { | 1146 | { |
| 1143 | struct flock fl; | 1147 | struct flock fl; |
| @@ -1188,11 +1192,43 @@ static long do_fcntl(int fd, int cmd, unsigned long arg) | @@ -1188,11 +1192,43 @@ static long do_fcntl(int fd, int cmd, unsigned long arg) | ||
| 1188 | 1192 | ||
| 1189 | void syscall_init(void) | 1193 | void syscall_init(void) |
| 1190 | { | 1194 | { |
| 1195 | + IOCTLEntry *ie; | ||
| 1196 | + const argtype *arg_type; | ||
| 1197 | + int size; | ||
| 1198 | + | ||
| 1191 | #define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); | 1199 | #define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); |
| 1192 | #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); | 1200 | #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); |
| 1193 | #include "syscall_types.h" | 1201 | #include "syscall_types.h" |
| 1194 | #undef STRUCT | 1202 | #undef STRUCT |
| 1195 | #undef STRUCT_SPECIAL | 1203 | #undef STRUCT_SPECIAL |
| 1204 | + | ||
| 1205 | + /* we patch the ioctl size if necessary. We rely on the fact that | ||
| 1206 | + no ioctl has all the bits at '1' in the size field */ | ||
| 1207 | + ie = ioctl_entries; | ||
| 1208 | + while (ie->target_cmd != 0) { | ||
| 1209 | + if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) == | ||
| 1210 | + TARGET_IOC_SIZEMASK) { | ||
| 1211 | + arg_type = ie->arg_type; | ||
| 1212 | + if (arg_type[0] != TYPE_PTR) { | ||
| 1213 | + fprintf(stderr, "cannot patch size for ioctl 0x%x\n", | ||
| 1214 | + ie->target_cmd); | ||
| 1215 | + exit(1); | ||
| 1216 | + } | ||
| 1217 | + arg_type++; | ||
| 1218 | + size = thunk_type_size(arg_type, 0); | ||
| 1219 | + ie->target_cmd = (ie->target_cmd & | ||
| 1220 | + ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) | | ||
| 1221 | + (size << TARGET_IOC_SIZESHIFT); | ||
| 1222 | + } | ||
| 1223 | + /* automatic consistency check if same arch */ | ||
| 1224 | +#if defined(__i386__) && defined(TARGET_I386) | ||
| 1225 | + if (ie->target_cmd != ie->host_cmd) { | ||
| 1226 | + fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n", | ||
| 1227 | + ie->target_cmd, ie->host_cmd); | ||
| 1228 | + } | ||
| 1229 | +#endif | ||
| 1230 | + ie++; | ||
| 1231 | + } | ||
| 1196 | } | 1232 | } |
| 1197 | 1233 | ||
| 1198 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | 1234 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |