From a5b3b13bedc545b5e571480b9cf47d2d378ad193 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 3 May 2010 10:07:55 -0700 Subject: 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 Signed-off-by: Aurelien Jarno --- linux-user/main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'linux-user/main.c') 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); } -- cgit v1.2.3-55-g7522