diff options
Diffstat (limited to 'linux-user')
-rw-r--r-- | linux-user/main.c | 11 | ||||
-rw-r--r-- | linux-user/syscall.c | 37 |
2 files changed, 43 insertions, 5 deletions
diff --git a/linux-user/main.c b/linux-user/main.c index b158bbc296..5027a6d994 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -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); } diff --git a/linux-user/syscall.c b/linux-user/syscall.c index fb18b24d2b..bca8f70f2c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -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 |