From patchwork Fri Mar 26 15:25:09 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 48656 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 F2D21B7CC2 for ; Sat, 27 Mar 2010 02:37:50 +1100 (EST) Received: from localhost ([127.0.0.1]:51739 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NvBYJ-0001IA-93 for incoming@patchwork.ozlabs.org; Fri, 26 Mar 2010 11:34:27 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NvBPY-0006bd-IW for qemu-devel@nongnu.org; Fri, 26 Mar 2010 11:25:24 -0400 Received: from [140.186.70.92] (port=38503 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NvBPU-0006Yt-DR for qemu-devel@nongnu.org; Fri, 26 Mar 2010 11:25:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1NvBPR-0000Sp-8M for qemu-devel@nongnu.org; Fri, 26 Mar 2010 11:25:20 -0400 Received: from afflict.kos.to ([92.243.29.197]:35009) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1NvBPR-0000Sd-0A for qemu-devel@nongnu.org; Fri, 26 Mar 2010 11:25:17 -0400 Received: by afflict.kos.to (Postfix, from userid 1000) id E4CD426595; Fri, 26 Mar 2010 15:25:15 +0000 (UTC) From: Riku Voipio To: qemu-devel@nongnu.org Date: Fri, 26 Mar 2010 15:25:09 +0000 Message-Id: X-Mailer: git-send-email 1.6.5 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) Cc: Riku Voipio , Michael Casadevall Subject: [Qemu-devel] [PATCH 1/4] linux-user: add pselect syscall 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 From: Michael Casadevall This patch adds support for the pselect syscall in linux-user emulation and also adds several support functions required to translate the timespec structs between the target and the host. Signed-off-by: Riku Voipio Signed-off-by: Michael Casadevall --- linux-user/syscall.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 119 insertions(+), 0 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 80d8633..845bb60 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -850,6 +850,38 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, return 0; } +static inline abi_long copy_from_user_timespec(struct timespec *ts, + abi_ulong target_ts_addr) +{ + struct target_timespec *target_ts; + + if (!lock_user_struct(VERIFY_READ, target_ts, target_ts_addr, 1)) + return -TARGET_EFAULT; + + __get_user(ts->tv_sec, &target_ts->tv_sec); + __get_user(ts->tv_nsec, &target_ts->tv_nsec); + + unlock_user_struct(target_ts, target_ts_addr, 0); + + return 0; +} + + +static inline abi_long copy_to_user_timespec(abi_ulong target_ts_addr, + const struct timespec *ts) +{ + struct target_timespec *target_ts; + + if (!lock_user_struct(VERIFY_WRITE, target_ts, target_ts_addr, 0)) + return -TARGET_EFAULT; + + __put_user(ts->tv_sec, &target_ts->tv_sec); + __put_user(ts->tv_nsec, &target_ts->tv_nsec); + + unlock_user_struct(target_ts, target_ts_addr, 1); + + return 0; +} #if defined(TARGET_NR_mq_open) && defined(__NR_mq_open) #include @@ -949,6 +981,75 @@ static abi_long do_select(int n, return ret; } +#ifdef TARGET_NR_pselect6 +/* do_pselect() must return target values and target errnos. */ +static abi_long do_pselect(int n, + abi_ulong rfd_addr, abi_ulong wfd_addr, + abi_ulong efd_addr, abi_ulong target_tv_addr, + abi_ulong set_addr) +{ + fd_set rfds, wfds, efds; + fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; + struct timespec tv, *tv_ptr; + sigset_t set, *set_ptr; + abi_long ret; + + if (rfd_addr) { + if (copy_from_user_fdset(&rfds, rfd_addr, n)) + return -TARGET_EFAULT; + rfds_ptr = &rfds; + } else { + rfds_ptr = NULL; + } + if (wfd_addr) { + if (copy_from_user_fdset(&wfds, wfd_addr, n)) + return -TARGET_EFAULT; + wfds_ptr = &wfds; + } else { + wfds_ptr = NULL; + } + if (efd_addr) { + if (copy_from_user_fdset(&efds, efd_addr, n)) + return -TARGET_EFAULT; + efds_ptr = &efds; + } else { + efds_ptr = NULL; + } + + if (target_tv_addr) { + if (copy_from_user_timespec(&tv, target_tv_addr)) + return -TARGET_EFAULT; + tv_ptr = &tv; + } else { + tv_ptr = NULL; + } + + /* We don't need to return sigmask to target */ + if (set_addr) { + target_to_host_old_sigset(&set, &set_addr); + set_ptr = &set; + } else { + set_ptr = NULL; + } + + ret = get_errno(pselect(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr, set_ptr)); + + if (!is_error(ret)) { + if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) + return -TARGET_EFAULT; + if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) + return -TARGET_EFAULT; + if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) + return -TARGET_EFAULT; + + if (target_tv_addr && copy_to_user_timespec(target_tv_addr, &tv)) + return -TARGET_EFAULT; + } + + return ret; +} +#endif + static abi_long do_pipe2(int host_pipe[], int flags) { #ifdef CONFIG_PIPE2 @@ -5186,6 +5287,24 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; #endif + +#ifdef TARGET_NR_pselect6 + case TARGET_NR_pselect6: + { + abi_ulong inp, outp, exp, tvp, set; + long nsel; + + nsel = tswapl(arg1); + inp = tswapl(arg2); + outp = tswapl(arg3); + exp = tswapl(arg4); + tvp = tswapl(arg5); + set = tswapl(arg6); + + ret = do_pselect(nsel, inp, outp, exp, tvp, set); + } + break; +#endif case TARGET_NR_symlink: { void *p2;