summaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-11-06 18:33:26 +0000
committerRiku Voipio <riku.voipio@linaro.org>2017-11-07 21:59:51 +0200
commit78bfef72fbf8705f002c5c57cf3f1d3b8e83399e (patch)
treea34b8c1c486f87655de8ae7f0dc5c0eaf8ca0520 /linux-user
parent8d8cb956e0a679fcf0a8e24f1b2f34e038cdd48e (diff)
downloadqemu-78bfef72fbf8705f002c5c57cf3f1d3b8e83399e.tar.gz
linux-user: Handle rt_sigaction correctly for SPARC
SPARC is like Alpha in its handling of the rt_sigaction syscall: it takes an extra parameter 'restorer' which needs to be copied into the sa_restorer field of the sigaction struct. The order of the arguments differs slightly between SPARC and Alpha but the implementation is otherwise the same. (Compare the rt_sigaction() functions in arch/sparc/kernel/sys_sparc_64.c and arch/alpha/kernel/signal.c.) Note that this change is somewhat moot until SPARC acquires support for actually delivering RT signals. Reviewed-by: Laurent Vivier <laurent@vivier.eu> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/syscall.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f31b853bb7..11c9116c4a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8579,8 +8579,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_rt_sigaction:
{
#if defined(TARGET_ALPHA)
- struct target_sigaction act, oact, *pact = 0;
+ /* For Alpha and SPARC this is a 5 argument syscall, with
+ * a 'restorer' parameter which must be copied into the
+ * sa_restorer field of the sigaction struct.
+ * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
+ * and arg5 is the sigsetsize.
+ * Alpha also has a separate rt_sigaction struct that it uses
+ * here; SPARC uses the usual sigaction struct.
+ */
struct target_rt_sigaction *rt_act;
+ struct target_sigaction act, oact, *pact = 0;
if (arg4 != sizeof(target_sigset_t)) {
ret = -TARGET_EINVAL;
@@ -8606,18 +8614,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user_struct(rt_act, arg3, 1);
}
#else
+#ifdef TARGET_SPARC
+ target_ulong restorer = arg4;
+ target_ulong sigsetsize = arg5;
+#else
+ target_ulong sigsetsize = arg4;
+#endif
struct target_sigaction *act;
struct target_sigaction *oact;
- if (arg4 != sizeof(target_sigset_t)) {
+ if (sigsetsize != sizeof(target_sigset_t)) {
ret = -TARGET_EINVAL;
break;
}
if (arg2) {
- if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
+ if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) {
goto efault;
- } else
+ }
+#ifdef TARGET_SPARC
+ act->sa_restorer = restorer;
+#endif
+ } else {
act = NULL;
+ }
if (arg3) {
if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
ret = -TARGET_EFAULT;