提交 a5b3b13b 编写于 作者: R Richard Henderson 提交者: Aurelien Jarno

alpha-linux-user: Fix sigprocmask.

Alpha passes oldset by value in a register, and returns the newset
as the return value; as compared to the standard implementation in
which both are passed by reference.  This requires being able to
distinguish negative return values that are not errors.  Do this in
the same way as the Alpha Linux kernel, by storing a zero in V0 in
the implementation of the syscall.

At the same time, fix a think-o in the regular sigprocmask path in
which we passed the target, rather than the host, HOW value.
Signed-off-by: NRichard Henderson <rth@twiddle.net>
Signed-off-by: NAurelien Jarno <aurelien@aurel32.net>
上级 f43ce12b
......@@ -2499,8 +2499,15 @@ void cpu_loop (CPUState *env)
env->ir[IR_A0], env->ir[IR_A1],
env->ir[IR_A2], env->ir[IR_A3],
env->ir[IR_A4], env->ir[IR_A5]);
if (trapnr != TARGET_NR_sigreturn
&& trapnr != TARGET_NR_rt_sigreturn) {
if (trapnr == TARGET_NR_sigreturn
|| trapnr == TARGET_NR_rt_sigreturn) {
break;
}
/* Syscall writes 0 to V0 to bypass error check, similar
to how this is handled internal to Linux kernel. */
if (env->ir[IR_V0] == 0) {
env->ir[IR_V0] = sysret;
} else {
env->ir[IR_V0] = (sysret < 0 ? -sysret : sysret);
env->ir[IR_A3] = (sysret < 0);
}
......
......@@ -4983,11 +4983,41 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#ifdef TARGET_NR_sigprocmask
case TARGET_NR_sigprocmask:
{
int how = arg1;
#if defined(TARGET_ALPHA)
sigset_t set, oldset;
abi_ulong mask;
int how;
switch (arg1) {
case TARGET_SIG_BLOCK:
how = SIG_BLOCK;
break;
case TARGET_SIG_UNBLOCK:
how = SIG_UNBLOCK;
break;
case TARGET_SIG_SETMASK:
how = SIG_SETMASK;
break;
default:
ret = -TARGET_EINVAL;
goto fail;
}
mask = arg2;
target_to_host_old_sigset(&set, &mask);
ret = get_errno(sigprocmask(how, &set, &oldset));
if (!is_error(ret)) {
host_to_target_old_sigset(&mask, &oldset);
ret = mask;
((CPUAlphaState *)cpu_env)->[IR_V0] = 0; /* force no error */
}
#else
sigset_t set, oldset, *set_ptr;
int how;
if (arg2) {
switch(how) {
switch (arg1) {
case TARGET_SIG_BLOCK:
how = SIG_BLOCK;
break;
......@@ -5010,13 +5040,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = 0;
set_ptr = NULL;
}
ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
ret = get_errno(sigprocmask(how, set_ptr, &oldset));
if (!is_error(ret) && arg3) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
goto efault;
host_to_target_old_sigset(p, &oldset);
unlock_user(p, arg3, sizeof(target_sigset_t));
}
#endif
}
break;
#endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册