diff options
author | Richard Henderson <rth@twiddle.net> | 2010-05-03 10:07:55 -0700 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2010-05-21 16:22:21 +0000 |
commit | a5b3b13bedc545b5e571480b9cf47d2d378ad193 (patch) | |
tree | a452a2d96839feebd033e8ec8357257ab3b79d37 /linux-user/main.c | |
parent | f43ce12b47323f0555ae9dfdf2f9d443346a4952 (diff) |
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: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'linux-user/main.c')
-rw-r--r-- | linux-user/main.c | 11 |
1 files changed, 9 insertions, 2 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); } |