From patchwork Mon Aug 29 18:38:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksandar Markovic X-Patchwork-Id: 9304327 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E1EA56077C for ; Mon, 29 Aug 2016 18:40:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D52B3281E1 for ; Mon, 29 Aug 2016 18:40:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C9A8A28761; Mon, 29 Aug 2016 18:40:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1ABFD281E1 for ; Mon, 29 Aug 2016 18:40:20 +0000 (UTC) Received: from localhost ([::1]:45187 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1beRTn-0004hb-7V for patchwork-qemu-devel@patchwork.kernel.org; Mon, 29 Aug 2016 14:40:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34647) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1beRTC-0004Y8-Q4 for qemu-devel@nongnu.org; Mon, 29 Aug 2016 14:39:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1beRT3-0000ae-SZ for qemu-devel@nongnu.org; Mon, 29 Aug 2016 14:39:42 -0400 Received: from mx2.rt-rk.com ([89.216.37.149]:37153 helo=mail.rt-rk.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1beRT3-0000Ru-FT for qemu-devel@nongnu.org; Mon, 29 Aug 2016 14:39:33 -0400 Received: from localhost (localhost [127.0.0.1]) by mail.rt-rk.com (Postfix) with ESMTP id 515241A416F; Mon, 29 Aug 2016 20:39:09 +0200 (CEST) X-Virus-Scanned: amavisd-new at rt-rk.com Received: from mcs19.ba.imgtec.org (unknown [82.117.201.26]) by mail.rt-rk.com (Postfix) with ESMTPSA id 2A09C1A4148; Mon, 29 Aug 2016 20:39:09 +0200 (CEST) From: Aleksandar Markovic To: riku.voipio@iki.fi Date: Mon, 29 Aug 2016 20:38:48 +0200 Message-Id: <1472495930-15155-2-git-send-email-aleksandar.markovic@rt-rk.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1472495930-15155-1-git-send-email-aleksandar.markovic@rt-rk.com> References: <1472495930-15155-1-git-send-email-aleksandar.markovic@rt-rk.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 89.216.37.149 Subject: [Qemu-devel] [PATCH 1/3] linux-user: Add support for adjtimex() syscall X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: miodrag.dinic@imgtec.com, aleksandar.markovic@imgtec.com, aleksandar.rikalo@imgtec.com, qemu-devel@nongnu.org, petar.jovanovic@imgtec.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Aleksandar Markovic This patch implements Qemu user mode adjtimex() syscall support. Syscall adjtimex() reads and optionally sets parameters for a clock adjustment algorithm used in network synchonization or similar scenarios. The implementation is based on invocation of host's adjtimex(), and its key part is in the correspondent case segment of the main switch statement of the function do_syscall(), in file linux-user/syscalls.c. Also, support for related structure "timex" is added to the file linux-user/syscall_defs.h, based on its definition in Linux kernel. All necessary conversions of the data structures from target to host and from host to target are covered. Two new functions, target_to_host_timex() and host_to_target_timex(), are provided for the purpose of such conversions. Moreover, the relevant support for "-strace" Qemu option is included in files linux-user/strace.c and linux-user/strace.list. This patch also fixes failures of LTP tests adjtimex01 and adjtimex02, if executed in Qemu user mode. Signed-off-by: Aleksandar Rikalo --- linux-user/strace.c | 12 +++++++ linux-user/strace.list | 2 +- linux-user/syscall.c | 86 ++++++++++++++++++++++++++++++++++++++++++++- linux-user/syscall_defs.h | 28 +++++++++++++++ 4 files changed, 126 insertions(+), 2 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index cc10dc4..7ddcaf8 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -919,6 +919,18 @@ print_access(const struct syscallname *name, } #endif +#ifdef TARGET_NR_adjtimex +static void +print_adjtimex(const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_pointer(arg0, 1); + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_brk static void print_brk(const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index aa967a2..9a665a8 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -16,7 +16,7 @@ { TARGET_NR_add_key, "add_key" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_adjtimex -{ TARGET_NR_adjtimex, "adjtimex" , NULL, NULL, NULL }, +{ TARGET_NR_adjtimex, "adjtimex" , NULL, print_adjtimex, NULL }, #endif #ifdef TARGET_NR_afs_syscall { TARGET_NR_afs_syscall, "afs_syscall" , NULL, NULL, NULL }, diff --git a/linux-user/syscall.c b/linux-user/syscall.c index ca06943..2190d41 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef __ia64__ int __clone2(int (*fn)(void *), void *child_stack_base, size_t stack_size, int flags, void *arg, ...); @@ -6578,6 +6579,76 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1, } #endif +static inline abi_long target_to_host_timex(struct timex *host_buf, + abi_long target_addr) +{ + struct target_timex *target_buf; + + if (!lock_user_struct(VERIFY_READ, target_buf, target_addr, 1)) { + return -TARGET_EFAULT; + } + + host_buf->modes = tswap32(target_buf->modes); + host_buf->offset = tswapal(target_buf->offset); + host_buf->freq = tswapal(target_buf->freq); + host_buf->maxerror = tswapal(target_buf->maxerror); + host_buf->esterror = tswapal(target_buf->esterror); + host_buf->status = tswap32(target_buf->status); + host_buf->constant = tswapal(target_buf->constant); + host_buf->precision = tswapal(target_buf->precision); + host_buf->tolerance = tswapal(target_buf->tolerance); + host_buf->time.tv_sec = tswapal(target_buf->time.tv_sec); + host_buf->time.tv_usec = tswapal(target_buf->time.tv_usec); + host_buf->tick = tswapal(target_buf->tick); + host_buf->ppsfreq = tswapal(target_buf->ppsfreq); + host_buf->jitter = tswapal(target_buf->jitter); + host_buf->shift = tswap32(target_buf->shift); + host_buf->stabil = tswapal(target_buf->stabil); + host_buf->jitcnt = tswapal(target_buf->jitcnt); + host_buf->calcnt = tswapal(target_buf->calcnt); + host_buf->errcnt = tswapal(target_buf->errcnt); + host_buf->stbcnt = tswapal(target_buf->stbcnt); + host_buf->tai = tswap32(target_buf->tai); + + unlock_user_struct(target_buf, target_addr, 0); + return 0; +} + +static inline abi_long host_to_target_timex(abi_long target_addr, + struct timex *host_buf) +{ + struct target_timex *target_buf; + + if (!lock_user_struct(VERIFY_WRITE, target_buf, target_addr, 0)) { + return -TARGET_EFAULT; + } + + target_buf->modes = tswap32(host_buf->modes); + target_buf->offset = tswapal(host_buf->offset); + target_buf->freq = tswapal(host_buf->freq); + target_buf->maxerror = tswapal(host_buf->maxerror); + target_buf->esterror = tswapal(host_buf->esterror); + target_buf->status = tswap32(host_buf->status); + target_buf->constant = tswapal(host_buf->constant); + target_buf->precision = tswapal(host_buf->precision); + target_buf->tolerance = tswapal(host_buf->tolerance); + target_buf->time.tv_sec = tswapal(host_buf->time.tv_sec); + target_buf->time.tv_usec = tswapal(host_buf->time.tv_usec); + target_buf->tick = tswapal(host_buf->tick); + target_buf->ppsfreq = tswapal(host_buf->ppsfreq); + target_buf->jitter = tswapal(host_buf->jitter); + target_buf->shift = tswap32(host_buf->shift); + target_buf->stabil = tswapal(host_buf->stabil); + target_buf->jitcnt = tswapal(host_buf->jitcnt); + target_buf->calcnt = tswapal(host_buf->calcnt); + target_buf->errcnt = tswapal(host_buf->errcnt); + target_buf->stbcnt = tswapal(host_buf->stbcnt); + target_buf->tai = tswap32(host_buf->tai); + + unlock_user_struct(target_buf, target_addr, 1); + return 0; +} + static inline abi_long target_to_host_timespec(struct timespec *host_ts, abi_ulong target_addr) { @@ -9420,7 +9491,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #endif case TARGET_NR_adjtimex: - goto unimplemented; + { + struct timex host_buf; + + if (target_to_host_timex(&host_buf, arg1) != 0) { + goto efault; + } + ret = get_errno(adjtimex(&host_buf)); + if (!is_error(ret) && arg1) { + if (host_to_target_timex(arg1, &host_buf) != 0) { + goto efault; + } + } + } + break; #ifdef TARGET_NR_create_module case TARGET_NR_create_module: #endif diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 7835654..afd9191 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -207,6 +207,34 @@ struct target_itimerspec { struct target_timespec it_value; }; +struct target_timex { + unsigned int modes; /* Mode selector */ + abi_long offset; /* Time offset */ + abi_long freq; /* Frequency offset */ + abi_long maxerror; /* Maximum error (microseconds) */ + abi_long esterror; /* Estimated error (microseconds) */ + int status; /* Clock command/status */ + abi_long constant; /* PLL (phase-locked loop) time constant */ + abi_long precision; /* Clock precision (microseconds, ro) */ + abi_long tolerance; /* Clock freq. tolerance (ppm, ro) */ + struct target_timeval time; /* Current time */ + abi_long tick; /* Microseconds between clock ticks */ + abi_long ppsfreq; /* PPS (pulse per second) frequency */ + abi_long jitter; /* PPS jitter (ro); nanoseconds */ + int shift; /* PPS interval duration (seconds) */ + abi_long stabil; /* PPS stability */ + abi_long jitcnt; /* PPS jitter limit exceeded (ro) */ + abi_long calcnt; /* PPS calibration intervals */ + abi_long errcnt; /* PPS calibration errors */ + abi_long stbcnt; /* PPS stability limit exceeded */ + int tai; /* TAI offset */ + + /* Further padding bytes to allow for future expansion */ + int:32; int:32; int:32; int:32; + int:32; int:32; int:32; int:32; + int:32; int:32; int:32; +}; + typedef abi_long target_clock_t; #define TARGET_HZ 100