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,6 +169,7 @@ void cpu_loop(CPUState *env);
169 void init_paths(const char *prefix); 169 void init_paths(const char *prefix);
170 const char *path(const char *pathname); 170 const char *path(const char *pathname);
171 char *target_strerror(int err); 171 char *target_strerror(int err);
  172 +int get_osversion(void);
172 173
173 extern int loglevel; 174 extern int loglevel;
174 extern FILE *logfile; 175 extern FILE *logfile;
linux-user/signal.c
@@ -1020,12 +1020,22 @@ struct target_sigcontext { @@ -1020,12 +1020,22 @@ struct target_sigcontext {
1020 abi_ulong fault_address; 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 abi_ulong tuc_flags; 1032 abi_ulong tuc_flags;
1025 abi_ulong tuc_link; 1033 abi_ulong tuc_link;
1026 target_stack_t tuc_stack; 1034 target_stack_t tuc_stack;
1027 struct target_sigcontext tuc_mcontext; 1035 struct target_sigcontext tuc_mcontext;
1028 target_sigset_t tuc_sigmask; /* mask last for extensibility */ 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 struct sigframe 1041 struct sigframe
@@ -1035,12 +1045,19 @@ struct sigframe @@ -1035,12 +1045,19 @@ struct sigframe
1035 abi_ulong retcode; 1045 abi_ulong retcode;
1036 }; 1046 };
1037 1047
1038 -struct rt_sigframe 1048 +struct rt_sigframe_v1
1039 { 1049 {
1040 abi_ulong pinfo; 1050 abi_ulong pinfo;
1041 abi_ulong puc; 1051 abi_ulong puc;
1042 struct target_siginfo info; 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 abi_ulong retcode; 1061 abi_ulong retcode;
1045 }; 1062 };
1046 1063
@@ -1191,11 +1208,11 @@ end: @@ -1191,11 +1208,11 @@ end:
1191 } 1208 }
1192 1209
1193 /* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */ 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 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame)); 1216 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1200 struct target_sigaltstack stack; 1217 struct target_sigaltstack stack;
1201 int i, err = 0; 1218 int i, err = 0;
@@ -1204,14 +1221,14 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, @@ -1204,14 +1221,14 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
1204 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) 1221 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1205 return /* 1 */; 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 __put_user_error(info_addr, &frame->pinfo, err); 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 __put_user_error(uc_addr, &frame->puc, err); 1227 __put_user_error(uc_addr, &frame->puc, err);
1211 err |= copy_siginfo_to_user(&frame->info, info); 1228 err |= copy_siginfo_to_user(&frame->info, info);
1212 1229
1213 /* Clear all the bits of the ucontext we don't use. */ 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 memset(&stack, 0, sizeof(stack)); 1233 memset(&stack, 0, sizeof(stack));
1217 __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp); 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,7 +1245,55 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
1228 1245
1229 if (err == 0) 1246 if (err == 0)
1230 err = setup_return(env, ka, &frame->retcode, frame_addr, usig, 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 if (err == 0) { 1298 if (err == 0) {
1234 /* 1299 /*
@@ -1246,6 +1311,17 @@ end: @@ -1246,6 +1311,17 @@ end:
1246 // return err; 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 static int 1325 static int
1250 restore_sigcontext(CPUState *env, struct target_sigcontext *sc) 1326 restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
1251 { 1327 {
@@ -1325,10 +1401,51 @@ badframe: @@ -1325,10 +1401,51 @@ badframe:
1325 return 0; 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 abi_ulong frame_addr; 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 sigset_t host_set; 1449 sigset_t host_set;
1333 1450
1334 /* 1451 /*
@@ -1349,7 +1466,7 @@ long do_rt_sigreturn(CPUState *env) @@ -1349,7 +1466,7 @@ long do_rt_sigreturn(CPUState *env)
1349 if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) 1466 if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
1350 goto badframe; 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 goto badframe; 1470 goto badframe;
1354 1471
1355 #if 0 1472 #if 0
@@ -1366,6 +1483,15 @@ badframe: @@ -1366,6 +1483,15 @@ badframe:
1366 return 0; 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 #elif defined(TARGET_SPARC) 1495 #elif defined(TARGET_SPARC)
1370 1496
1371 #define __SUNOS_MAXWIN 31 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,6 +3054,37 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3054 unlock_user_struct(target_ts, target_addr, 1); 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 /* do_syscall() should always have a single exit point at the end so 3088 /* do_syscall() should always have a single exit point at the end so
3058 that actions, such as logging of syscall results, can be performed. 3089 that actions, such as logging of syscall results, can be performed.
3059 All errnos that do_syscall() returns must be -TARGET_<errcode>. */ 3090 All errnos that do_syscall() returns must be -TARGET_<errcode>. */