Commit a745ec6d91fc3ee06b4c281d30b472aeaa6302e0

Authored by pbrook
1 parent f0b86b14

Update ARM rt_frame layout.



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4365 c046a42c-6fe2-441c-8c8c-71466251a162
linux-user/qemu.h
... ... @@ -169,6 +169,7 @@ void cpu_loop(CPUState *env);
169 169 void init_paths(const char *prefix);
170 170 const char *path(const char *pathname);
171 171 char *target_strerror(int err);
  172 +int get_osversion(void);
172 173  
173 174 extern int loglevel;
174 175 extern FILE *logfile;
... ...
linux-user/signal.c
... ... @@ -1020,12 +1020,22 @@ struct target_sigcontext {
1020 1020 abi_ulong fault_address;
1021 1021 };
1022 1022  
1023   -struct target_ucontext {
  1023 +struct target_ucontext_v1 {
  1024 + abi_ulong tuc_flags;
  1025 + abi_ulong tuc_link;
  1026 + target_stack_t tuc_stack;
  1027 + struct target_sigcontext tuc_mcontext;
  1028 + target_sigset_t tuc_sigmask; /* mask last for extensibility */
  1029 +};
  1030 +
  1031 +struct target_ucontext_v2 {
1024 1032 abi_ulong tuc_flags;
1025 1033 abi_ulong tuc_link;
1026 1034 target_stack_t tuc_stack;
1027 1035 struct target_sigcontext tuc_mcontext;
1028 1036 target_sigset_t tuc_sigmask; /* mask last for extensibility */
  1037 + char __unused[128 - sizeof(sigset_t)];
  1038 + abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1029 1039 };
1030 1040  
1031 1041 struct sigframe
... ... @@ -1035,12 +1045,19 @@ struct sigframe
1035 1045 abi_ulong retcode;
1036 1046 };
1037 1047  
1038   -struct rt_sigframe
  1048 +struct rt_sigframe_v1
1039 1049 {
1040 1050 abi_ulong pinfo;
1041 1051 abi_ulong puc;
1042 1052 struct target_siginfo info;
1043   - struct target_ucontext uc;
  1053 + struct target_ucontext_v1 uc;
  1054 + abi_ulong retcode;
  1055 +};
  1056 +
  1057 +struct rt_sigframe_v2
  1058 +{
  1059 + struct target_siginfo info;
  1060 + struct target_ucontext_v2 uc;
1044 1061 abi_ulong retcode;
1045 1062 };
1046 1063  
... ... @@ -1191,11 +1208,11 @@ end:
1191 1208 }
1192 1209  
1193 1210 /* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
1194   -static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
1195   - target_siginfo_t *info,
1196   - target_sigset_t *set, CPUState *env)
  1211 +static void setup_rt_frame_v1(int usig, struct emulated_sigaction *ka,
  1212 + target_siginfo_t *info,
  1213 + target_sigset_t *set, CPUState *env)
1197 1214 {
1198   - struct rt_sigframe *frame;
  1215 + struct rt_sigframe_v1 *frame;
1199 1216 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1200 1217 struct target_sigaltstack stack;
1201 1218 int i, err = 0;
... ... @@ -1204,14 +1221,14 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
1204 1221 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1205 1222 return /* 1 */;
1206 1223  
1207   - info_addr = frame_addr + offsetof(struct rt_sigframe, info);
  1224 + info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1208 1225 __put_user_error(info_addr, &frame->pinfo, err);
1209   - uc_addr = frame_addr + offsetof(struct rt_sigframe, uc);
  1226 + uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1210 1227 __put_user_error(uc_addr, &frame->puc, err);
1211 1228 err |= copy_siginfo_to_user(&frame->info, info);
1212 1229  
1213 1230 /* Clear all the bits of the ucontext we don't use. */
1214   - memset(&frame->uc, 0, offsetof(struct target_ucontext, tuc_mcontext));
  1231 + memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
1215 1232  
1216 1233 memset(&stack, 0, sizeof(stack));
1217 1234 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
... ... @@ -1228,7 +1245,55 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
1228 1245  
1229 1246 if (err == 0)
1230 1247 err = setup_return(env, ka, &frame->retcode, frame_addr, usig,
1231   - frame_addr + offsetof(struct rt_sigframe, retcode));
  1248 + frame_addr + offsetof(struct rt_sigframe_v1, retcode));
  1249 +
  1250 + if (err == 0) {
  1251 + env->regs[1] = info_addr;
  1252 + env->regs[2] = uc_addr;
  1253 + }
  1254 +
  1255 +end:
  1256 + unlock_user_struct(frame, frame_addr, 1);
  1257 +
  1258 + // return err;
  1259 +}
  1260 +
  1261 +static void setup_rt_frame_v2(int usig, struct emulated_sigaction *ka,
  1262 + target_siginfo_t *info,
  1263 + target_sigset_t *set, CPUState *env)
  1264 +{
  1265 + struct rt_sigframe_v2 *frame;
  1266 + abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
  1267 + struct target_sigaltstack stack;
  1268 + int i, err = 0;
  1269 + abi_ulong info_addr, uc_addr;
  1270 +
  1271 + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
  1272 + return /* 1 */;
  1273 +
  1274 + info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
  1275 + uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
  1276 + err |= copy_siginfo_to_user(&frame->info, info);
  1277 +
  1278 + /* Clear all the bits of the ucontext we don't use. */
  1279 + memset(&frame->uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
  1280 +
  1281 + memset(&stack, 0, sizeof(stack));
  1282 + __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
  1283 + __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
  1284 + __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
  1285 + memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
  1286 +
  1287 + err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/
  1288 + env, set->sig[0]);
  1289 + for(i = 0; i < TARGET_NSIG_WORDS; i++) {
  1290 + if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
  1291 + goto end;
  1292 + }
  1293 +
  1294 + if (err == 0)
  1295 + err = setup_return(env, ka, &frame->retcode, frame_addr, usig,
  1296 + frame_addr + offsetof(struct rt_sigframe_v2, retcode));
1232 1297  
1233 1298 if (err == 0) {
1234 1299 /*
... ... @@ -1246,6 +1311,17 @@ end:
1246 1311 // return err;
1247 1312 }
1248 1313  
  1314 +static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
  1315 + target_siginfo_t *info,
  1316 + target_sigset_t *set, CPUState *env)
  1317 +{
  1318 + if (get_osversion() >= 0x020612) {
  1319 + setup_rt_frame_v2(usig, ka, info, set, env);
  1320 + } else {
  1321 + setup_rt_frame_v1(usig, ka, info, set, env);
  1322 + }
  1323 +}
  1324 +
1249 1325 static int
1250 1326 restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
1251 1327 {
... ... @@ -1325,10 +1401,51 @@ badframe:
1325 1401 return 0;
1326 1402 }
1327 1403  
1328   -long do_rt_sigreturn(CPUState *env)
  1404 +long do_rt_sigreturn_v1(CPUState *env)
1329 1405 {
1330 1406 abi_ulong frame_addr;
1331   - struct rt_sigframe *frame;
  1407 + struct rt_sigframe_v1 *frame;
  1408 + sigset_t host_set;
  1409 +
  1410 + /*
  1411 + * Since we stacked the signal on a 64-bit boundary,
  1412 + * then 'sp' should be word aligned here. If it's
  1413 + * not, then the user is trying to mess with us.
  1414 + */
  1415 + if (env->regs[13] & 7)
  1416 + goto badframe;
  1417 +
  1418 + frame_addr = env->regs[13];
  1419 + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
  1420 + goto badframe;
  1421 +
  1422 + target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
  1423 + sigprocmask(SIG_SETMASK, &host_set, NULL);
  1424 +
  1425 + if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
  1426 + goto badframe;
  1427 +
  1428 + if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
  1429 + goto badframe;
  1430 +
  1431 +#if 0
  1432 + /* Send SIGTRAP if we're single-stepping */
  1433 + if (ptrace_cancel_bpt(current))
  1434 + send_sig(SIGTRAP, current, 1);
  1435 +#endif
  1436 + unlock_user_struct(frame, frame_addr, 0);
  1437 + return env->regs[0];
  1438 +
  1439 +badframe:
  1440 + unlock_user_struct(frame, frame_addr, 0);
  1441 + force_sig(SIGSEGV /* , current */);
  1442 + return 0;
  1443 +}
  1444 +
  1445 +long do_rt_sigreturn_v2(CPUState *env)
  1446 +{
  1447 + abi_ulong frame_addr;
  1448 + struct rt_sigframe_v2 *frame;
1332 1449 sigset_t host_set;
1333 1450  
1334 1451 /*
... ... @@ -1349,7 +1466,7 @@ long do_rt_sigreturn(CPUState *env)
1349 1466 if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
1350 1467 goto badframe;
1351 1468  
1352   - if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
  1469 + if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v2, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1353 1470 goto badframe;
1354 1471  
1355 1472 #if 0
... ... @@ -1366,6 +1483,15 @@ badframe:
1366 1483 return 0;
1367 1484 }
1368 1485  
  1486 +long do_rt_sigreturn(CPUState *env)
  1487 +{
  1488 + if (get_osversion() >= 0x020612) {
  1489 + return do_rt_sigreturn_v2(env);
  1490 + } else {
  1491 + return do_rt_sigreturn_v1(env);
  1492 + }
  1493 +}
  1494 +
1369 1495 #elif defined(TARGET_SPARC)
1370 1496  
1371 1497 #define __SUNOS_MAXWIN 31
... ...
linux-user/syscall.c
... ... @@ -3054,6 +3054,37 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3054 3054 unlock_user_struct(target_ts, target_addr, 1);
3055 3055 }
3056 3056  
  3057 +int get_osversion(void)
  3058 +{
  3059 + static int osversion;
  3060 + struct new_utsname buf;
  3061 + const char *s;
  3062 + int i, n, tmp;
  3063 + if (osversion)
  3064 + return osversion;
  3065 + if (qemu_uname_release && *qemu_uname_release) {
  3066 + s = qemu_uname_release;
  3067 + } else {
  3068 + if (sys_uname(&buf))
  3069 + return 0;
  3070 + s = buf.release;
  3071 + }
  3072 + tmp = 0;
  3073 + for (i = 0; i < 3; i++) {
  3074 + n = 0;
  3075 + while (*s >= '0' && *s <= '9') {
  3076 + n *= 10;
  3077 + n += *s - '0';
  3078 + s++;
  3079 + }
  3080 + tmp = (tmp << 8) + n;
  3081 + if (*s == '.')
  3082 + s++;
  3083 + }
  3084 + osversion = tmp;
  3085 + return osversion;
  3086 +}
  3087 +
3057 3088 /* do_syscall() should always have a single exit point at the end so
3058 3089 that actions, such as logging of syscall results, can be performed.
3059 3090 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
... ...