From patchwork Mon May 3 17:07:55 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 51521 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id ADED6B7D1B for ; Tue, 4 May 2010 04:45:35 +1000 (EST) Received: from localhost ([127.0.0.1]:36115 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O8zOV-0002zz-NY for incoming@patchwork.ozlabs.org; Mon, 03 May 2010 13:25:23 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O8z8W-0007fa-0q for qemu-devel@nongnu.org; Mon, 03 May 2010 13:08:52 -0400 Received: from [140.186.70.92] (port=59113 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O8z8U-0007fC-5K for qemu-devel@nongnu.org; Mon, 03 May 2010 13:08:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O8z8S-0000HH-Ce for qemu-devel@nongnu.org; Mon, 03 May 2010 13:08:49 -0400 Received: from mail-qy0-f188.google.com ([209.85.221.188]:62982) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O8z8S-0000Bh-6q for qemu-devel@nongnu.org; Mon, 03 May 2010 13:08:48 -0400 Received: by mail-qy0-f188.google.com with SMTP id 26so4137992qyk.19 for ; Mon, 03 May 2010 10:08:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:sender:from:to:subject:date :message-id:x-mailer:in-reply-to:references; bh=LdFSOEtf0INnpk0J/npIN6jbeqgNlhsHD1dp8y47cyQ=; b=EHPF9N6BY4hos7Xlpg2om9GbmR7jcna0E6O+6Al7N2F+rrTEt7/4kDp2v4kT/toiRg MlYxpNKUOHmINQ9AJZ4SxDXmF++cX9/6Vy6JiBATPHytB3wCybvvwqNQ6rvVMWXIGL6/ DSxSXS6F1HhCcSn7EcuWGIaUeFQrS2wvBgeJc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:to:subject:date:message-id:x-mailer:in-reply-to :references; b=ChHdHDNRxePeYvR4GP/DethA+8Je1JiSlKbG0mndK2SgbRPx8WQ6Iq5iY3g7v58//F aGzHVS+tqCkz8czLbwbUripiJ2DNiJpIoGNui9HP8lHPPtY6W6V+ifU9fUpQZ6abhxQM EdpyCDkPxU725glCieN4STmZsvrJIXXlXe1yg= Received: by 10.224.66.100 with SMTP id m36mr3392899qai.126.1272906527783; Mon, 03 May 2010 10:08:47 -0700 (PDT) Received: from localhost.localdomain (are.twiddle.net [75.149.56.221]) by mx.google.com with ESMTPS id 2sm9954190qwi.29.2010.05.03.10.08.46 (version=TLSv1/SSLv3 cipher=RC4-MD5); Mon, 03 May 2010 10:08:47 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Mon, 3 May 2010 10:07:55 -0700 Message-Id: <1272906475-14480-8-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.6.6.1 In-Reply-To: <1272906475-14480-7-git-send-email-rth@twiddle.net> References: <1272906475-14480-1-git-send-email-rth@twiddle.net> <1272906475-14480-2-git-send-email-rth@twiddle.net> <1272906475-14480-3-git-send-email-rth@twiddle.net> <1272906475-14480-4-git-send-email-rth@twiddle.net> <1272906475-14480-5-git-send-email-rth@twiddle.net> <1272906475-14480-6-git-send-email-rth@twiddle.net> <1272906475-14480-7-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) Subject: [Qemu-devel] [PATCH 7/7] alpha-linux-user: Fix sigprocmask. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- linux-user/main.c | 11 +++++++++-- 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 e35c124..2862355 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 899b76f..6f88943 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4967,11 +4967,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; @@ -4994,13 +5024,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