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 | 68 | #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) |
| 69 | 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 | 71 | #define __NR_sys_uname __NR_uname |
| 77 | 72 | #define __NR_sys_getcwd1 __NR_getcwd |
| 78 | 73 | #define __NR_sys_statfs __NR_statfs |
| ... | ... | @@ -702,8 +697,8 @@ enum { |
| 702 | 697 | #undef STRUCT_SPECIAL |
| 703 | 698 | |
| 704 | 699 | typedef struct IOCTLEntry { |
| 705 | - int target_cmd; | |
| 706 | - int host_cmd; | |
| 700 | + unsigned int target_cmd; | |
| 701 | + unsigned int host_cmd; | |
| 707 | 702 | const char *name; |
| 708 | 703 | int access; |
| 709 | 704 | const argtype arg_type[5]; |
| ... | ... | @@ -715,7 +710,7 @@ typedef struct IOCTLEntry { |
| 715 | 710 | |
| 716 | 711 | #define MAX_STRUCT_SIZE 4096 |
| 717 | 712 | |
| 718 | -const IOCTLEntry ioctl_entries[] = { | |
| 713 | +IOCTLEntry ioctl_entries[] = { | |
| 719 | 714 | #define IOCTL(cmd, access, types...) \ |
| 720 | 715 | { TARGET_ ## cmd, cmd, #cmd, access, { types } }, |
| 721 | 716 | #include "ioctls.h" |
| ... | ... | @@ -970,7 +965,7 @@ static bitmask_transtbl mmap_flags_tbl[] = { |
| 970 | 965 | { 0, 0, 0, 0 } |
| 971 | 966 | }; |
| 972 | 967 | |
| 973 | -#ifdef TARGET_I386 | |
| 968 | +#if defined(TARGET_I386) | |
| 974 | 969 | |
| 975 | 970 | /* NOTE: there is really one LDT for all the threads */ |
| 976 | 971 | uint8_t *ldt_table; |
| ... | ... | @@ -1087,28 +1082,28 @@ int do_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount |
| 1087 | 1082 | return ret; |
| 1088 | 1083 | } |
| 1089 | 1084 | |
| 1085 | +#endif /* defined(TARGET_I386) */ | |
| 1086 | + | |
| 1090 | 1087 | /* this stack is the equivalent of the kernel stack associated with a |
| 1091 | 1088 | thread/process */ |
| 1092 | 1089 | #define NEW_STACK_SIZE 8192 |
| 1093 | 1090 | |
| 1094 | 1091 | static int clone_func(void *arg) |
| 1095 | 1092 | { |
| 1096 | - CPUX86State *env = arg; | |
| 1093 | + CPUState *env = arg; | |
| 1097 | 1094 | cpu_loop(env); |
| 1098 | 1095 | /* never exits */ |
| 1099 | 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 | 1101 | int ret; |
| 1105 | 1102 | TaskState *ts; |
| 1106 | 1103 | uint8_t *new_stack; |
| 1107 | - CPUX86State *new_env; | |
| 1104 | + CPUState *new_env; | |
| 1108 | 1105 | |
| 1109 | 1106 | if (flags & CLONE_VM) { |
| 1110 | - if (!newsp) | |
| 1111 | - newsp = env->regs[R_ESP]; | |
| 1112 | 1107 | ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); |
| 1113 | 1108 | memset(ts, 0, sizeof(TaskState)); |
| 1114 | 1109 | new_stack = ts->stack; |
| ... | ... | @@ -1117,10 +1112,21 @@ int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) |
| 1117 | 1112 | ts->next = first_task_state; |
| 1118 | 1113 | first_task_state = ts; |
| 1119 | 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 | 1120 | new_env->regs[R_ESP] = newsp; |
| 1123 | 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 | 1130 | new_env->opaque = ts; |
| 1125 | 1131 | #ifdef __ia64__ |
| 1126 | 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 | 1142 | return ret; |
| 1137 | 1143 | } |
| 1138 | 1144 | |
| 1139 | -#endif | |
| 1140 | - | |
| 1141 | 1145 | static long do_fcntl(int fd, int cmd, unsigned long arg) |
| 1142 | 1146 | { |
| 1143 | 1147 | struct flock fl; |
| ... | ... | @@ -1188,11 +1192,43 @@ static long do_fcntl(int fd, int cmd, unsigned long arg) |
| 1188 | 1192 | |
| 1189 | 1193 | void syscall_init(void) |
| 1190 | 1194 | { |
| 1195 | + IOCTLEntry *ie; | |
| 1196 | + const argtype *arg_type; | |
| 1197 | + int size; | |
| 1198 | + | |
| 1191 | 1199 | #define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); |
| 1192 | 1200 | #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); |
| 1193 | 1201 | #include "syscall_types.h" |
| 1194 | 1202 | #undef STRUCT |
| 1195 | 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 | 1234 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ... | ... |