Module Name:    src
Committed By:   thorpej
Date:           Sun Sep 19 23:51:37 UTC 2021

Modified Files:
        src/sys/compat/linux/arch/alpha: syscalls.master
        src/sys/compat/linux/arch/amd64: syscalls.master
        src/sys/compat/linux/arch/arm: syscalls.master
        src/sys/compat/linux/arch/i386: syscalls.master
        src/sys/compat/linux/arch/m68k: syscalls.master
        src/sys/compat/linux/arch/mips: syscalls.master
        src/sys/compat/linux/arch/powerpc: syscalls.master
        src/sys/compat/linux/common: linux_ioctl.c linux_ioctl.h linux_sched.h
            linux_time.c
        src/sys/compat/linux32/arch/amd64: syscalls.master
        src/sys/compat/linux32/common: linux32_ioctl.c linux32_time.c

Log Message:
Add the timerfd syscalls to COMPAT_LINUX and COMPAT_LINUX32.


To generate a diff of this commit:
cvs rdiff -u -r1.98 -r1.99 src/sys/compat/linux/arch/alpha/syscalls.master
cvs rdiff -u -r1.63 -r1.64 src/sys/compat/linux/arch/amd64/syscalls.master
cvs rdiff -u -r1.70 -r1.71 src/sys/compat/linux/arch/arm/syscalls.master
cvs rdiff -u -r1.125 -r1.126 src/sys/compat/linux/arch/i386/syscalls.master
cvs rdiff -u -r1.96 -r1.97 src/sys/compat/linux/arch/m68k/syscalls.master
cvs rdiff -u -r1.69 -r1.70 src/sys/compat/linux/arch/mips/syscalls.master
cvs rdiff -u -r1.75 -r1.76 src/sys/compat/linux/arch/powerpc/syscalls.master
cvs rdiff -u -r1.58 -r1.59 src/sys/compat/linux/common/linux_ioctl.c
cvs rdiff -u -r1.27 -r1.28 src/sys/compat/linux/common/linux_ioctl.h
cvs rdiff -u -r1.9 -r1.10 src/sys/compat/linux/common/linux_sched.h
cvs rdiff -u -r1.41 -r1.42 src/sys/compat/linux/common/linux_time.c
cvs rdiff -u -r1.72 -r1.73 src/sys/compat/linux32/arch/amd64/syscalls.master
cvs rdiff -u -r1.14 -r1.15 src/sys/compat/linux32/common/linux32_ioctl.c
cvs rdiff -u -r1.39 -r1.40 src/sys/compat/linux32/common/linux32_time.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/compat/linux/arch/alpha/syscalls.master
diff -u src/sys/compat/linux/arch/alpha/syscalls.master:1.98 src/sys/compat/linux/arch/alpha/syscalls.master:1.99
--- src/sys/compat/linux/arch/alpha/syscalls.master:1.98	Sun Sep 19 23:01:49 2021
+++ src/sys/compat/linux/arch/alpha/syscalls.master	Sun Sep 19 23:51:36 2021
@@ -1,4 +1,4 @@
-	$NetBSD: syscalls.master,v 1.98 2021/09/19 23:01:49 thorpej Exp $
+	$NetBSD: syscalls.master,v 1.99 2021/09/19 23:51:36 thorpej Exp $
 ;
 ;	@(#)syscalls.master	8.1 (Berkeley) 7/19/93
 
@@ -770,9 +770,13 @@
 			    unsigned int flags, struct timespec *timeout); }
 480	STD		{ int|linux_sys||fallocate(int fd, int mode, \
 			    off_t offset, off_t len); }
-481	UNIMPL		timerfd_create
-482	UNIMPL		timerfd_settime
-483	UNIMPL		timerfd_gettime
+481	STD		{ int|linux_sys||timerfd_create(clockid_t clock_id, \
+			    int flags); }
+482	STD		{ int|linux_sys||timerfd_settime(int fd, int flags, \
+			    const struct linux_itimerspec *tim, \
+			    struct linux_itimerspec *otim); }
+483	STD		{ int|linux_sys||timerfd_gettime(int fd, \
+			    struct linux_itimerspec *tim); }
 484	UNIMPL		signalfd4
 485	UNIMPL		eventfd2
 486	UNIMPL		epoll_create1

Index: src/sys/compat/linux/arch/amd64/syscalls.master
diff -u src/sys/compat/linux/arch/amd64/syscalls.master:1.63 src/sys/compat/linux/arch/amd64/syscalls.master:1.64
--- src/sys/compat/linux/arch/amd64/syscalls.master:1.63	Sun Sep 19 23:01:49 2021
+++ src/sys/compat/linux/arch/amd64/syscalls.master	Sun Sep 19 23:51:36 2021
@@ -1,4 +1,4 @@
-	$NetBSD: syscalls.master,v 1.63 2021/09/19 23:01:49 thorpej Exp $
+	$NetBSD: syscalls.master,v 1.64 2021/09/19 23:51:36 thorpej Exp $
 
 ;	@(#)syscalls.master	8.1 (Berkeley) 7/19/93
 
@@ -519,12 +519,16 @@
 			    struct linux_timespec *times, int flag); }
 281	UNIMPL		epoll_pwait
 282	UNIMPL		signalfd
-283	UNIMPL		timerfd_create
+283	STD		{ int|linux_sys||timerfd_create(clockid_t clock_id, \
+			    int flags); }
 284	UNIMPL		eventfd
 285	STD		{ int|linux_sys||fallocate(int fd, int mode, \
 			    off_t offset, off_t len); }
-286	UNIMPL		timerfd_settime
-287	UNIMPL		timerfd_gettime
+286	STD		{ int|linux_sys||timerfd_settime(int fd, int flags, \
+			    const struct linux_itimerspec *tim, \
+			    struct linux_itimerspec *otim); }
+287	STD		{ int|linux_sys||timerfd_gettime(int fd, \
+			    struct linux_itimerspec *tim); }
 288	STD		{ int|linux_sys||accept4(int s, \
 			    struct osockaddr *name, \
 			    int *anamelen, int flags); }

Index: src/sys/compat/linux/arch/arm/syscalls.master
diff -u src/sys/compat/linux/arch/arm/syscalls.master:1.70 src/sys/compat/linux/arch/arm/syscalls.master:1.71
--- src/sys/compat/linux/arch/arm/syscalls.master:1.70	Sun Sep 19 23:01:49 2021
+++ src/sys/compat/linux/arch/arm/syscalls.master	Sun Sep 19 23:51:36 2021
@@ -1,4 +1,4 @@
-	$NetBSD: syscalls.master,v 1.70 2021/09/19 23:01:49 thorpej Exp $
+	$NetBSD: syscalls.master,v 1.71 2021/09/19 23:51:36 thorpej Exp $
 
 ; Derived from sys/compat/linux/arch/*/syscalls.master
 ; and from Linux 2.4.12 arch/arm/kernel/calls.S
@@ -562,12 +562,16 @@
 348	STD		{ int|linux_sys||utimensat(int fd, const char *path, \
 			    struct linux_timespec *times, int flag); }
 349	UNIMPL		signalfd
-350	UNIMPL		timerfd_create
+350	STD		{ int|linux_sys||timerfd_create(clockid_t clock_id, \
+			    int flags); }
 351	UNIMPL		eventfd
 352	STD		{ int|linux_sys||fallocate(int fd, int mode, \
 			    off_t offset, off_t len); }
-353	UNIMPL		timerfd_settime
-354	UNIMPL		timerfd_gettime
+353	STD		{ int|linux_sys||timerfd_settime(int fd, int flags, \
+			    const struct linux_itimerspec *tim, \
+			    struct linux_itimerspec *otim); }
+354	STD		{ int|linux_sys||timerfd_gettime(int fd, \
+			    struct linux_itimerspec *tim); }
 355	UNIMPL		signalfd4
 356	UNIMPL		eventfd2
 357	UNIMPL		epoll_create1

Index: src/sys/compat/linux/arch/i386/syscalls.master
diff -u src/sys/compat/linux/arch/i386/syscalls.master:1.125 src/sys/compat/linux/arch/i386/syscalls.master:1.126
--- src/sys/compat/linux/arch/i386/syscalls.master:1.125	Sun Sep 19 23:01:50 2021
+++ src/sys/compat/linux/arch/i386/syscalls.master	Sun Sep 19 23:51:36 2021
@@ -1,4 +1,4 @@
-	$NetBSD: syscalls.master,v 1.125 2021/09/19 23:01:50 thorpej Exp $
+	$NetBSD: syscalls.master,v 1.126 2021/09/19 23:51:36 thorpej Exp $
 
 ;	@(#)syscalls.master	8.1 (Berkeley) 7/19/93
 
@@ -529,12 +529,16 @@
 320	STD		{ int|linux_sys||utimensat(int fd, const char *path, \
 			    struct linux_timespec *times, int flag); }
 321	UNIMPL		signalfd
-322	UNIMPL		timerfd_create
+322	STD		{ int|linux_sys||timerfd_create(clockid_t clock_id, \
+			    int flags); }
 323	UNIMPL		eventfd
 324	STD		{ int|linux_sys||fallocate(int fd, int mode, \
 			    off_t offset, off_t len); }
-325	UNIMPL		timerfd_settime
-326	UNIMPL		timerfd_gettime
+325	STD		{ int|linux_sys||timerfd_settime(int fd, int flags, \
+			    const struct linux_itimerspec *tim, \
+			    struct linux_itimerspec *otim); }
+326	STD		{ int|linux_sys||timerfd_gettime(int fd, \
+			    struct linux_itimerspec *tim); }
 327	UNIMPL		signalfd4
 328	UNIMPL		eventfd2
 329	UNIMPL		epoll_create1

Index: src/sys/compat/linux/arch/m68k/syscalls.master
diff -u src/sys/compat/linux/arch/m68k/syscalls.master:1.96 src/sys/compat/linux/arch/m68k/syscalls.master:1.97
--- src/sys/compat/linux/arch/m68k/syscalls.master:1.96	Sun Sep 19 23:01:50 2021
+++ src/sys/compat/linux/arch/m68k/syscalls.master	Sun Sep 19 23:51:36 2021
@@ -1,4 +1,4 @@
-	$NetBSD: syscalls.master,v 1.96 2021/09/19 23:01:50 thorpej Exp $
+	$NetBSD: syscalls.master,v 1.97 2021/09/19 23:51:36 thorpej Exp $
 
 ;	@(#)syscalls.master	8.1 (Berkeley) 7/19/93
 
@@ -547,12 +547,16 @@
 316	STD		{ int|linux_sys||utimensat(int fd, const char *path, \
 			    struct linux_timespec *times, int flag); }
 317	UNIMPL		signalfd
-318	UNIMPL		timerfd_create
+318	STD		{ int|linux_sys||timerfd_create(clockid_t clock_id, \
+			    int flags); }
 319	UNIMPL		eventfd
 320	STD		{ int|linux_sys||fallocate(int fd, int mode, \
 			    off_t offset, off_t len); }
-321	UNIMPL		timerfd_settime
-322	UNIMPL		timerfd_gettime
+321	STD		{ int|linux_sys||timerfd_settime(int fd, int flags, \
+			    const struct linux_itimerspec *tim, \
+			    struct linux_itimerspec *otim); }
+322	STD		{ int|linux_sys||timerfd_gettime(int fd, \
+			    struct linux_itimerspec *tim); }
 323	UNIMPL		signalfd4
 324	UNIMPL		eventfd2
 325	UNIMPL		epoll_create1

Index: src/sys/compat/linux/arch/mips/syscalls.master
diff -u src/sys/compat/linux/arch/mips/syscalls.master:1.69 src/sys/compat/linux/arch/mips/syscalls.master:1.70
--- src/sys/compat/linux/arch/mips/syscalls.master:1.69	Sun Sep 19 23:01:50 2021
+++ src/sys/compat/linux/arch/mips/syscalls.master	Sun Sep 19 23:51:37 2021
@@ -1,4 +1,4 @@
-	$NetBSD: syscalls.master,v 1.69 2021/09/19 23:01:50 thorpej Exp $  
+	$NetBSD: syscalls.master,v 1.70 2021/09/19 23:51:37 thorpej Exp $  
 
 ;	@(#)syscalls.master	8.1 (Berkeley) 7/19/93
 
@@ -539,9 +539,13 @@
 319	UNIMPL		eventfd
 320	STD		{ int|linux_sys||fallocate(int fd, int mode, \
 			    off_t offset, off_t len); }
-321	UNIMPL		timerfd_create
-322	UNIMPL		timerfd_gettime
-323	UNIMPL		timerfd_settime
+321	STD		{ int|linux_sys||timerfd_create(clockid_t clock_id, \
+			    int flags); }
+322	STD		{ int|linux_sys||timerfd_gettime(int fd, \
+			    struct linux_itimerspec *tim); }
+323	STD		{ int|linux_sys||timerfd_settime(int fd, int flags, \
+			    const struct linux_itimerspec *tim, \
+			    struct linux_itimerspec *otim); }
 324	UNIMPL		signalfd4
 325	UNIMPL		eventfd2
 326	UNIMPL		epoll_create1

Index: src/sys/compat/linux/arch/powerpc/syscalls.master
diff -u src/sys/compat/linux/arch/powerpc/syscalls.master:1.75 src/sys/compat/linux/arch/powerpc/syscalls.master:1.76
--- src/sys/compat/linux/arch/powerpc/syscalls.master:1.75	Sun Sep 19 23:01:50 2021
+++ src/sys/compat/linux/arch/powerpc/syscalls.master	Sun Sep 19 23:51:37 2021
@@ -1,4 +1,4 @@
-	$NetBSD: syscalls.master,v 1.75 2021/09/19 23:01:50 thorpej Exp $  
+	$NetBSD: syscalls.master,v 1.76 2021/09/19 23:51:37 thorpej Exp $  
 
 ;	@(#)syscalls.master	8.1 (Berkeley) 7/19/93
 
@@ -533,14 +533,18 @@
 304	STD		{ int|linux_sys||utimensat(int fd, const char *path, \
 			    struct linux_timespec *times, int flag); }
 305	UNIMPL		signalfd
-306	UNIMPL		timerfd_create
+306	STD		{ int|linux_sys||timerfd_create(clockid_t clock_id, \
+			    int flags); }
 307	UNIMPL		eventfd
 308	UNIMPL		sync_file_range2
 309	STD		{ int|linux_sys||fallocate(int fd, int mode, \
 			    off_t offset, off_t len); }
 310	UNIMPL		subpage_prot
-311	UNIMPL		timerfd_settime
-312	UNIMPL		timerfd_gettime
+311	STD		{ int|linux_sys||timerfd_settime(int fd, int flags, \
+			    const struct linux_itimerspec *tim, \
+			    struct linux_itimerspec *otim); }
+312	STD		{ int|linux_sys||timerfd_gettime(int fd, \
+			    struct linux_itimerspec *tim); }
 313	UNIMPL		signalfd4
 314	UNIMPL		eventfd2
 315	UNIMPL		epoll_create1

Index: src/sys/compat/linux/common/linux_ioctl.c
diff -u src/sys/compat/linux/common/linux_ioctl.c:1.58 src/sys/compat/linux/common/linux_ioctl.c:1.59
--- src/sys/compat/linux/common/linux_ioctl.c:1.58	Sun Mar 23 06:03:38 2014
+++ src/sys/compat/linux/common/linux_ioctl.c	Sun Sep 19 23:51:37 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_ioctl.c,v 1.58 2014/03/23 06:03:38 dholland Exp $	*/
+/*	$NetBSD: linux_ioctl.c,v 1.59 2021/09/19 23:51:37 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_ioctl.c,v 1.58 2014/03/23 06:03:38 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_ioctl.c,v 1.59 2021/09/19 23:51:37 thorpej Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "sequencer.h"
@@ -144,46 +144,49 @@ linux_sys_ioctl(struct lwp *l, const str
 		error = linux_ioctl_mtio(l, uap, retval);
 		break;
 	case 'T':
-	{
-#if NSEQUENCER > 0
-/* XXX XAX 2x check this. */
+	    {
 		/*
-		 * Both termios and the MIDI sequencer use 'T' to identify
-		 * the ioctl, so we have to differentiate them in another
-		 * way.  We do it by indexing in the cdevsw with the major
-		 * device number and check if that is the sequencer entry.
+		 * Termios, the MIDI sequencer, and timerfd use 'T' to
+		 * identify the ioctl, so we have to differentiate them
+		 * in another way.
+		 *
+		 * XXX XAX 2x check this.
 		 */
-		bool is_sequencer = false;
 		struct file *fp;
-		struct vnode *vp;
-		struct vattr va;
-		extern const struct cdevsw sequencer_cdevsw;
 
 		if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
 			return EBADF;
+
+		if (fp->f_type == DTYPE_TIMERFD) {
+			error = linux_ioctl_timerfd(l, uap, retval);
+			fd_putfile(SCARG(uap, fd));
+			break;
+		}
+#if NSEQUENCER > 0
+		struct vnode *vp;
+
 		if (fp->f_type == DTYPE_VNODE &&
 		    (vp = (struct vnode *)fp->f_data) != NULL &&
 		    vp->v_type == VCHR) {
+			struct vattr va;
+			extern const struct cdevsw sequencer_cdevsw;
+
 			vn_lock(vp, LK_SHARED | LK_RETRY);
 			error = VOP_GETATTR(vp, &va, l->l_cred);
 			VOP_UNLOCK(vp);
 			if (error == 0 &&
-			    cdevsw_lookup(va.va_rdev) == &sequencer_cdevsw)
-				is_sequencer = true;
-		}
-		if (is_sequencer) {
-			error = oss_ioctl_sequencer(l, (const void *)LINUX_TO_OSS(uap),
-						   retval);
-		}
-		else {
-			error = linux_ioctl_termios(l, uap, retval);
+			    cdevsw_lookup(va.va_rdev) == &sequencer_cdevsw) {
+				error = oss_ioctl_sequencer(l,
+				    (const void *)LINUX_TO_OSS(uap), retval);
+				fd_putfile(SCARG(uap, fd));
+				break;
+			}
 		}
-		fd_putfile(SCARG(uap, fd));
-#else
+#endif /* NSEQUENCER > 0 */
 		error = linux_ioctl_termios(l, uap, retval);
-#endif
-	}
+		fd_putfile(SCARG(uap, fd));
 		break;
+	    }
 	case '"':
 		error = linux_ioctl_sg(l, uap, retval);
 		break;

Index: src/sys/compat/linux/common/linux_ioctl.h
diff -u src/sys/compat/linux/common/linux_ioctl.h:1.27 src/sys/compat/linux/common/linux_ioctl.h:1.28
--- src/sys/compat/linux/common/linux_ioctl.h:1.27	Sat Jun  8 12:50:32 2013
+++ src/sys/compat/linux/common/linux_ioctl.h	Sun Sep 19 23:51:37 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_ioctl.h,v 1.27 2013/06/08 12:50:32 stacktic Exp $	*/
+/*	$NetBSD: linux_ioctl.h,v 1.28 2021/09/19 23:51:37 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
@@ -41,6 +41,8 @@ int linux_ioctl_cdrom(struct lwp *, cons
     register_t *);
 int linux_ioctl_termios(struct lwp *, const struct linux_sys_ioctl_args *,
     register_t *);
+int linux_ioctl_timerfd(struct lwp *, const struct linux_sys_ioctl_args *,
+    register_t *);
 int linux_ioctl_socket(struct lwp *, const struct linux_sys_ioctl_args *,
     register_t *);
 int linux_ioctl_hdio(struct lwp *, const struct linux_sys_ioctl_args *,

Index: src/sys/compat/linux/common/linux_sched.h
diff -u src/sys/compat/linux/common/linux_sched.h:1.9 src/sys/compat/linux/common/linux_sched.h:1.10
--- src/sys/compat/linux/common/linux_sched.h:1.9	Sun Sep 19 23:01:50 2021
+++ src/sys/compat/linux/common/linux_sched.h	Sun Sep 19 23:51:37 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_sched.h,v 1.9 2021/09/19 23:01:50 thorpej Exp $	*/
+/*	$NetBSD: linux_sched.h,v 1.10 2021/09/19 23:51:37 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -106,4 +106,6 @@ void	linux_to_native_itimerspec(struct i
 
 int	linux_to_native_timer_create_clockid(clockid_t *, clockid_t);
 
+int	linux_to_native_timerfd_settime_flags(int *, int);
+
 #endif /* _LINUX_SCHED_H */

Index: src/sys/compat/linux/common/linux_time.c
diff -u src/sys/compat/linux/common/linux_time.c:1.41 src/sys/compat/linux/common/linux_time.c:1.42
--- src/sys/compat/linux/common/linux_time.c:1.41	Sun Sep 19 23:01:50 2021
+++ src/sys/compat/linux/common/linux_time.c	Sun Sep 19 23:51:37 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_time.c,v 1.41 2021/09/19 23:01:50 thorpej Exp $ */
+/*	$NetBSD: linux_time.c,v 1.42 2021/09/19 23:51:37 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2001, 2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.41 2021/09/19 23:01:50 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.42 2021/09/19 23:51:37 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/ucred.h>
@@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c
 #include <sys/signal.h>
 #include <sys/stdint.h>
 #include <sys/time.h>
+#include <sys/timerfd.h>
 #include <sys/systm.h>
 #include <sys/sched.h>
 #include <sys/syscallargs.h>
@@ -46,6 +47,8 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c
 #include <sys/proc.h>
 
 #include <compat/linux/common/linux_types.h>
+#include <compat/linux/common/linux_fcntl.h>
+#include <compat/linux/common/linux_ioctl.h>
 #include <compat/linux/common/linux_signal.h>
 #include <compat/linux/common/linux_sigevent.h>
 #include <compat/linux/common/linux_machdep.h>
@@ -441,3 +444,149 @@ linux_sys_timer_gettime(struct lwp *l,
  * timer_gettoverrun(2) and timer_delete(2) are handled directly
  * by the native calls.
  */
+
+#define	LINUX_TFD_TIMER_ABSTIME		0x0001
+#define	LINUX_TFD_TIMER_CANCEL_ON_SET	0x0002
+#define	LINUX_TFD_CLOEXEC		LINUX_O_CLOEXEC
+#define	LINUX_TFD_NONBLOCK		LINUX_O_NONBLOCK
+
+int
+linux_sys_timerfd_create(struct lwp *l,
+    const struct linux_sys_timerfd_create_args *uap, register_t *retval)
+{
+	/* {
+		syscallarg(clockid_t) clock_id;
+		syscallarg(int) flags;
+	} */
+	int nflags = 0;
+	clockid_t id;
+	int error;
+
+	error = linux_to_native_clockid(&id, SCARG(uap, clock_id));
+	if (error) {
+		return error;
+	}
+
+	if (SCARG(uap, flags) & ~(LINUX_TFD_CLOEXEC | LINUX_TFD_NONBLOCK)) {
+		return EINVAL;
+	}
+	if (SCARG(uap, flags) & LINUX_TFD_CLOEXEC) {
+		nflags |= TFD_CLOEXEC;
+	}
+	if (SCARG(uap, flags) & LINUX_TFD_NONBLOCK) {
+		nflags |= TFD_NONBLOCK;
+	}
+
+	return do_timerfd_create(l, id, nflags, retval);
+}
+
+int
+linux_sys_timerfd_gettime(struct lwp *l,
+    const struct linux_sys_timerfd_gettime_args *uap, register_t *retval)
+{
+	/* {
+		syscallarg(int) fd;
+		syscallarg(struct linux_itimerspec *) tim;
+	} */
+	struct itimerspec its;
+	struct linux_itimerspec lits;
+	int error;
+
+	error = do_timerfd_gettime(l, SCARG(uap, fd), &its, retval);
+	if (error == 0) {
+		native_to_linux_itimerspec(&lits, &its);
+		error = copyout(&lits, SCARG(uap, tim), sizeof(lits));
+	}
+
+	return error;
+}
+
+int
+linux_to_native_timerfd_settime_flags(int *nflagsp, int lflags)
+{
+	int nflags = 0;
+
+	if (lflags & ~(LINUX_TFD_TIMER_ABSTIME |
+		       LINUX_TFD_TIMER_CANCEL_ON_SET)) {
+		return EINVAL;
+	}
+	if (lflags & LINUX_TFD_TIMER_ABSTIME) {
+		nflags |= TFD_TIMER_ABSTIME;
+	}
+	if (lflags & LINUX_TFD_TIMER_CANCEL_ON_SET) {
+		nflags |= TFD_TIMER_CANCEL_ON_SET;
+	}
+
+	*nflagsp = nflags;
+
+	return 0;
+}
+
+int
+linux_sys_timerfd_settime(struct lwp *l,
+    const struct linux_sys_timerfd_settime_args *uap, register_t *retval)
+{
+	/* {
+		syscallarg(int) fd;
+		syscallarg(int) flags;
+		syscallarg(const struct linux_itimerspec *) tim;
+		syscallarg(struct linux_itimerspec *) otim;
+	} */
+	struct itimerspec nits, oits, *oitsp = NULL;
+	struct linux_itimerspec lits;
+	int nflags;
+	int error;
+
+	error = copyin(SCARG(uap, tim), &lits, sizeof(lits));
+	if (error) {
+		return error;
+	}
+	linux_to_native_itimerspec(&nits, &lits);
+
+	error = linux_to_native_timerfd_settime_flags(&nflags,
+	    SCARG(uap, flags));
+	if (error) {
+		return error;
+	}
+
+	if (SCARG(uap, otim)) {
+		oitsp = &oits;
+	}
+
+	error = do_timerfd_settime(l, SCARG(uap, fd), nflags,
+	    &nits, oitsp, retval);
+	if (error == 0 && oitsp != NULL) {
+		native_to_linux_itimerspec(&lits, oitsp);
+		error = copyout(&lits, SCARG(uap, otim), sizeof(lits));
+	}
+
+	return error;
+}
+
+#define	LINUX_TFD_IOC_SET_TICKS		_LINUX_IOW('T', 0, uint64_t)
+
+int
+linux_ioctl_timerfd(struct lwp *l, const struct linux_sys_ioctl_args *uap,
+    register_t *retval)
+{
+	/* {
+		syscallarg(int) fd;
+		syscallarg(u_long) com;
+		syscallarg(void *) data;
+	} */
+	struct sys_ioctl_args ua;
+
+	SCARG(&ua, fd) = SCARG(uap, fd);
+	SCARG(&ua, data) = SCARG(uap, data);
+
+	switch (SCARG(uap, com)) {
+	case LINUX_TFD_IOC_SET_TICKS:
+		SCARG(&ua, com) = TFD_IOC_SET_TICKS;
+		break;
+
+	default:
+		return EINVAL;
+	}
+
+	return sys_ioctl(l, (const void *)&ua, retval);
+}

Index: src/sys/compat/linux32/arch/amd64/syscalls.master
diff -u src/sys/compat/linux32/arch/amd64/syscalls.master:1.72 src/sys/compat/linux32/arch/amd64/syscalls.master:1.73
--- src/sys/compat/linux32/arch/amd64/syscalls.master:1.72	Sun Sep 19 23:01:50 2021
+++ src/sys/compat/linux32/arch/amd64/syscalls.master	Sun Sep 19 23:51:37 2021
@@ -1,4 +1,4 @@
-	$NetBSD: syscalls.master,v 1.72 2021/09/19 23:01:50 thorpej Exp $
+	$NetBSD: syscalls.master,v 1.73 2021/09/19 23:51:37 thorpej Exp $
 
 ; NetBSD i386 COMPAT_LINUX32 system call name/number "master" file.
 ; (See syscalls.conf to see what it is processed into.)
@@ -550,12 +550,16 @@
 320	STD	{ int|linux32_sys||utimensat(int fd, netbsd32_charp path, \
 			    linux32_timespecp_t times, int flag); }
 321	UNIMPL	signalfd
-322	UNIMPL	timerfd_create
+322	NOARGS	{ int|linux_sys||timerfd_create(clockid_t clock_id, \
+		    int flags); }
 323	UNIMPL	eventfd
 324	STD	{ int|linux32_sys||fallocate(int fd, int mode, \
 			    off_t offset, off_t len); }
-325	UNIMPL	timerfd_settime
-326	UNIMPL	timerfd_gettime
+325	STD	{ int|linux32_sys||timerfd_settime(int fd, int flags, \
+		    const struct linux32_itimerspec *tim, \
+		    struct linux32_itimerspec *otim); }
+326	STD	{ int|linux32_sys||timerfd_gettime(int fd, \
+		    struct linux32_itimerspec *tim); }
 327	UNIMPL	signalfd4
 328	UNIMPL	eventfd2
 329	UNIMPL	epoll_create1

Index: src/sys/compat/linux32/common/linux32_ioctl.c
diff -u src/sys/compat/linux32/common/linux32_ioctl.c:1.14 src/sys/compat/linux32/common/linux32_ioctl.c:1.15
--- src/sys/compat/linux32/common/linux32_ioctl.c:1.14	Fri Aug 23 12:49:59 2019
+++ src/sys/compat/linux32/common/linux32_ioctl.c	Sun Sep 19 23:51:37 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux32_ioctl.c,v 1.14 2019/08/23 12:49:59 maxv Exp $ */
+/*	$NetBSD: linux32_ioctl.c,v 1.15 2021/09/19 23:51:37 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
@@ -32,13 +32,15 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux32_ioctl.c,v 1.14 2019/08/23 12:49:59 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux32_ioctl.c,v 1.15 2021/09/19 23:51:37 thorpej Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/ucred.h>
 #include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
 
 #include <compat/netbsd32/netbsd32.h>
 #include <compat/netbsd32/netbsd32_syscallargs.h>
@@ -46,6 +48,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_ioct
 #include <compat/linux/common/linux_types.h>
 #include <compat/linux/common/linux_signal.h>
 #include <compat/linux/common/linux_ipc.h>
+#include <compat/linux/common/linux_ioctl.h>
 #include <compat/linux/common/linux_sem.h>
 #include <compat/linux/linux_syscallargs.h>
 
@@ -80,8 +83,31 @@ linux32_sys_ioctl(struct lwp *l, const s
 
 	switch(group) {
 	case 'T':
-		error = linux32_ioctl_termios(l, uap, retval);
+	    {
+		/*
+		 * Termios, the MIDI sequencer, and timerfd use 'T' to
+		 * identify the ioctl, so we have to differentiate them
+		 * in another way.
+		 *
+		 * (XXX We don't bother with MIDI here.)
+		 */
+		struct file *fp;
+
+		if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
+			return EBADF;
+
+		if (fp->f_type == DTYPE_TIMERFD) {
+			struct linux_sys_ioctl_args ua;
+			SCARG(&ua, fd) = SCARG(uap, fd);
+			SCARG(&ua, com) = SCARG(uap, com);
+			SCARG(&ua, data) = SCARG_P32(uap, data);
+			error = linux_ioctl_timerfd(l, &ua, retval);
+		} else {
+			error = linux32_ioctl_termios(l, uap, retval);
+		}
+		fd_putfile(SCARG(uap, fd));
 		break;
+	    }
 	case 'M':
 	case 'Q':
 	case 'P':

Index: src/sys/compat/linux32/common/linux32_time.c
diff -u src/sys/compat/linux32/common/linux32_time.c:1.39 src/sys/compat/linux32/common/linux32_time.c:1.40
--- src/sys/compat/linux32/common/linux32_time.c:1.39	Sun Sep 19 23:01:50 2021
+++ src/sys/compat/linux32/common/linux32_time.c	Sun Sep 19 23:51:37 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux32_time.c,v 1.39 2021/09/19 23:01:50 thorpej Exp $ */
+/*	$NetBSD: linux32_time.c,v 1.40 2021/09/19 23:51:37 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
@@ -33,7 +33,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: linux32_time.c,v 1.39 2021/09/19 23:01:50 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux32_time.c,v 1.40 2021/09/19 23:51:37 thorpej Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -45,6 +45,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_time
 #include <sys/fcntl.h>
 #include <sys/namei.h>
 #include <sys/select.h>
+#include <sys/timerfd.h>
 #include <sys/proc.h>
 #include <sys/resourcevar.h>
 #include <sys/ucred.h>
@@ -498,3 +499,69 @@ linux32_sys_timer_gettime(struct lwp *l,
  * timer_gettoverrun(2) and timer_delete(2) are handled directly
  * by the native calls.
  */
+
+/*
+ * timerfd_create() is handled by the standard COMPAT_LINUX call.
+ */
+
+int
+linux32_sys_timerfd_gettime(struct lwp *l,
+    const struct linux32_sys_timerfd_gettime_args *uap, register_t *retval)
+{
+	/* {
+		syscallarg(int) fd;
+		syscallarg(struct linux32_itimerspec *) tim;
+	} */
+	struct itimerspec its;
+	struct linux32_itimerspec lits;
+	int error;
+
+	error = do_timerfd_gettime(l, SCARG(uap, fd), &its, retval);
+	if (error == 0) {
+		native_to_linux32_itimerspec(&lits, &its);
+		error = copyout(&lits, SCARG(uap, tim), sizeof(lits));
+	}
+
+	return error;
+}
+
+int
+linux32_sys_timerfd_settime(struct lwp *l,
+    const struct linux32_sys_timerfd_settime_args *uap, register_t *retval)
+{
+	/* {
+		syscallarg(int) fd;
+		syscallarg(int) flags;
+		syscallarg(const struct linux32_itimerspec *) tim;
+		syscallarg(struct linux32_itimerspec *) otim;
+	} */
+	struct itimerspec nits, oits, *oitsp = NULL;
+	struct linux32_itimerspec lits;
+	int nflags;
+	int error;
+
+	error = copyin(SCARG(uap, tim), &lits, sizeof(lits));
+	if (error) {
+		return error;
+	}
+	linux32_to_native_itimerspec(&nits, &lits);
+
+	error = linux_to_native_timerfd_settime_flags(&nflags,
+	    SCARG(uap, flags));
+	if (error) {
+		return error;
+	}
+
+	if (SCARG(uap, otim)) {
+		oitsp = &oits;
+	}
+
+	error = do_timerfd_settime(l, SCARG(uap, fd), nflags,
+	    &nits, oitsp, retval);
+	if (error == 0 && oitsp != NULL) {
+		native_to_linux32_itimerspec(&lits, oitsp);
+		error = copyout(&lits, SCARG(uap, otim), sizeof(lits));
+	}
+
+	return error;
+}

Reply via email to