Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 31 May 2026 17:19:57 +0000
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 510ee6698d37 - main - linux_ntsync: linux compat shim for ntsync(9)
Message-ID:  <6a1c6dbd.3efb2.7c6d34dd@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=510ee6698d377f4a9a4eeb08d9dc17bdc72ad5ab

commit 510ee6698d377f4a9a4eeb08d9dc17bdc72ad5ab
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-05-19 02:23:33 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-05-31 17:17:07 +0000

    linux_ntsync: linux compat shim for ntsync(9)
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D57038
---
 sys/dev/ntsync/linux_ntsync.c     | 302 ++++++++++++++++++++++++++++++++++++++
 sys/dev/ntsync/linux_ntsync.h     |  62 ++++++++
 sys/modules/Makefile              |   1 +
 sys/modules/linux_ntsync/Makefile |   6 +
 4 files changed, 371 insertions(+)

diff --git a/sys/dev/ntsync/linux_ntsync.c b/sys/dev/ntsync/linux_ntsync.c
new file mode 100644
index 000000000000..064e8c6aede9
--- /dev/null
+++ b/sys/dev/ntsync/linux_ntsync.c
@@ -0,0 +1,302 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2026 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ */
+
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <dev/ntsync/ntsyncvar.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_common.h>
+#include <compat/linux/linux_ioctl.h>
+#include <dev/ntsync/linux_ntsync.h>
+
+MODULE_DEPEND(linux_ntsync, linux, 1, 1, 1);
+MODULE_DEPEND(linux_ntsync, ntsync, 1, 1, 1);
+
+static linux_ioctl_function_t linux_ntsync_ioctl;
+static struct linux_ioctl_handler linux_ntsync_handler = {linux_ntsync_ioctl,
+    LNTSYNC_IOCTL_MIN, LNTSYNC_IOCTL_MAX};
+
+static int
+linux_ntsync_modevent(module_t mod __unused, int type, void *data __unused)
+{
+	int error;
+
+	error = 0;
+	switch (type) {
+	case MOD_LOAD:
+		error = linux_ioctl_register_handler(&linux_ntsync_handler);
+		if (error != 0) {
+			printf("linux_ntsync: cannot register ioctl handler, "
+			    "error %d\n", error);
+		} else if (bootverbose)
+			printf("linux_ntsync\n");
+		break;
+
+	case MOD_UNLOAD:
+		linux_ioctl_unregister_handler(&linux_ntsync_handler);
+		break;
+
+	case MOD_SHUTDOWN:
+		break;
+
+	default:
+		error = EOPNOTSUPP;
+	}
+
+	return (error);
+}
+
+DEV_MODULE(linux_ntsync, linux_ntsync_modevent, NULL);
+MODULE_VERSION(linux_ntsync, 1);
+
+/* XXXKIB no translation of structs */
+static void
+ntsync_lsa_to_sa(struct ntsync_sem_args *sa,
+    const struct linux_ntsync_sem_args *lsa)
+{
+	memcpy(sa, lsa, sizeof(*sa));
+}
+
+static void
+ntsync_sa_to_lsa(struct linux_ntsync_sem_args *lsa,
+    const struct ntsync_sem_args *sa)
+{
+	memcpy(lsa, sa, sizeof(*lsa));
+}
+
+static void
+ntsync_lma_to_ma(struct ntsync_mutex_args *ma,
+    const struct linux_ntsync_mutex_args *lma)
+{
+	memcpy(ma, lma, sizeof(*ma));
+}
+
+static void
+ntsync_ma_to_lma(struct linux_ntsync_mutex_args *ma,
+    const struct ntsync_mutex_args *lma)
+{
+	memcpy(ma, lma, sizeof(*ma));
+}
+
+static void
+ntsync_lea_to_ea(struct ntsync_event_args *ea,
+    const struct linux_ntsync_event_args *lea)
+{
+	memcpy(ea, lea, sizeof(*ea));
+}
+
+static void
+ntsync_ea_to_lea(struct linux_ntsync_event_args *lea,
+    const struct ntsync_event_args *ea)
+{
+	memcpy(lea, ea, sizeof(*lea));
+}
+
+static void
+ntsync_lwa_to_wa(struct ntsync_wait_args *wa,
+    const struct linux_ntsync_wait_args *lwa)
+{
+	memcpy(wa, lwa, sizeof(*wa));
+}
+
+static void
+ntsync_wa_to_lwa(struct linux_ntsync_wait_args *lwa,
+    const struct ntsync_wait_args *wa)
+{
+	memcpy(lwa, wa, sizeof(*lwa));
+}
+
+static int
+linux_ntsync_cdev_ioctl(struct thread *td, u_long cmd, void *data,
+    struct file *fp)
+{
+	struct cdev *dev;
+	struct cdevsw *dsw;
+	struct vnode *vp;
+	struct file *fpop;
+	int error, ref;
+
+	if (fp->f_type != DTYPE_VNODE)
+		return (error = ENOIOCTL);
+
+	vp = fp->f_vnode;
+	if (vp->v_type != VCHR)
+		return (ENOIOCTL);
+	dev = vp->v_rdev;
+	dsw = dev_refthread(dev, &ref);
+	if (dsw == NULL)
+		return (ENXIO);
+	if (dsw != &ntsync_cdevsw) {
+		error = ENOIOCTL;
+	} else {
+		fpop = td->td_fpop;
+		td->td_fpop = fp;
+		error = dsw->d_ioctl(dev, cmd, data, 0, td);
+		td->td_fpop = fpop;
+	}
+	dev_relthread(dev, ref);
+	return (error);
+}
+
+static int
+linux_ntsync_ioctl(struct thread *td, struct linux_ioctl_args *args)
+{
+	struct file *fp;
+	void *data;
+	struct linux_ntsync_sem_args lsa;
+	struct linux_ntsync_mutex_args lma;
+	struct linux_ntsync_event_args lea;
+	struct linux_ntsync_wait_args lwa;
+	struct ntsync_sem_args sa;
+	struct ntsync_mutex_args ma;
+	struct ntsync_event_args ea;
+	struct ntsync_wait_args wa;
+	uint32_t val;
+	int error, error1, lcmd;
+	bool doco;
+
+	lcmd = args->cmd;
+	data = (void *)args->arg;
+
+	error = fget_cap(td, args->fd, &cap_no_rights, NULL, &fp, NULL);
+	if (error != 0)
+		goto out;
+
+	doco = false;
+	switch (lcmd) {
+	case LNTSYNC_IOC_CREATE_SEM:
+		error = copyin(data, &lsa, sizeof(lsa));
+		ntsync_lsa_to_sa(&sa, &lsa);
+		if (error == 0) {
+			error = linux_ntsync_cdev_ioctl(td,
+			    NTSYNC_IOC_CREATE_SEM, &sa, fp);
+		}
+		break;
+	case LNTSYNC_IOC_CREATE_MUTEX:
+		error = copyin(data, &lma, sizeof(lma));
+		ntsync_lma_to_ma(&ma, &lma);
+		if (error == 0) {
+			error = linux_ntsync_cdev_ioctl(td,
+			    NTSYNC_IOC_CREATE_MUTEX, &ma, fp);
+		}
+		break;
+	case LNTSYNC_IOC_CREATE_EVENT:
+		error = copyin(data, &lea, sizeof(lea));
+		ntsync_lea_to_ea(&ea, &lea);
+		if (error == 0) {
+			error = linux_ntsync_cdev_ioctl(td,
+			    NTSYNC_IOC_CREATE_EVENT, &ea, fp);
+		}
+		break;
+	case LNTSYNC_IOC_WAIT_ANY:
+		error = copyin(data, &lwa, sizeof(lwa));
+		ntsync_lwa_to_wa(&wa, &lwa);
+		if (error == 0) {
+			error = linux_ntsync_cdev_ioctl(td,
+			    NTSYNC_IOC_WAIT_ANY, &wa, fp);
+			if (error == 0 || error == EOWNERDEAD) {
+				ntsync_wa_to_lwa(&lwa, &wa);
+				error1 = copyout(&lwa, data, sizeof(lwa));
+				if (error == 0)
+					error = error1;
+			}
+		}
+		break;
+	case LNTSYNC_IOC_WAIT_ALL:
+		error = copyin(data, &lwa, sizeof(lwa));
+		ntsync_lwa_to_wa(&wa, &lwa);
+		if (error == 0) {
+			error = linux_ntsync_cdev_ioctl(td,
+			    NTSYNC_IOC_WAIT_ALL, &wa, fp);
+			if (error == 0 || error == EOWNERDEAD) {
+				ntsync_wa_to_lwa(&lwa, &wa);
+				error1 = copyout(&lwa, data, sizeof(lwa));
+				if (error == 0)
+					error = error1;
+			}
+		}
+		break;
+	case LNTSYNC_IOC_SEM_RELEASE:
+		error = copyin(data, &val, sizeof(val));
+		if (error == 0) {
+			error = ntsync_sem_release(td, fp, &val);
+			if (error == 0)
+				error = copyout(&val, data, sizeof(val));
+		}
+		break;
+	case LNTSYNC_IOC_SEM_READ:
+		error = ntsync_sem_read(td, fp, &sa);
+		if (error == 0) {
+			ntsync_sa_to_lsa(&lsa, &sa);
+			error = copyout(&lsa, data, sizeof(lsa));
+		}
+		break;
+	case LNTSYNC_IOC_MUTEX_UNLOCK:
+		error = copyin(data, &lma, sizeof(lma));
+		ntsync_lma_to_ma(&ma, &lma);
+		if (error == 0) {
+			error = ntsync_mutex_unlock(td, fp, &ma);
+			if (error == 0) {
+				ntsync_ma_to_lma(&lma, &ma);
+				error = copyout(&lma, data, sizeof(lma));
+			}
+		}
+		break;
+	case LNTSYNC_IOC_MUTEX_KILL:
+		error = copyin(data, &val, sizeof(val));
+		if (error == 0)
+			error = ntsync_mutex_kill(td, fp, val);
+		break;
+	case LNTSYNC_IOC_MUTEX_READ:
+		error = ntsync_mutex_read(td, fp, &ma, &doco);
+		if (doco) {
+			ntsync_ma_to_lma(&lma, &ma);
+			error1 = copyout(&lma, data, sizeof(lma));
+			if (error == 0)
+				error = error1;
+		}
+		break;
+	case LNTSYNC_IOC_EVENT_SET:
+		error = ntsync_event_set(td, fp, &val);
+		if (error == 0)
+			error = copyout(&val, data, sizeof(val));
+		break;
+	case LNTSYNC_IOC_EVENT_RESET:
+		error = ntsync_event_reset(td, fp, &val);
+		if (error == 0)
+			error = copyout(&val, data, sizeof(val));
+		break;
+	case LNTSYNC_IOC_EVENT_PULSE:
+		error = ntsync_event_pulse(td, fp, &val);
+		if (error == 0)
+			error = copyout(&val, data, sizeof(val));
+		break;
+	case LNTSYNC_IOC_EVENT_READ:
+		error = ntsync_event_read(td, fp, &ea);
+		if (error == 0) {
+			ntsync_ea_to_lea(&lea, &ea);
+			error = copyout(&lea, data, sizeof(lea));
+		}
+		break;
+	default:
+		error = ENOTTY;
+		break;
+	}
+	fdrop(fp, td);
+out:
+	return (error);
+}
diff --git a/sys/dev/ntsync/linux_ntsync.h b/sys/dev/ntsync/linux_ntsync.h
new file mode 100644
index 000000000000..412eca00bb1e
--- /dev/null
+++ b/sys/dev/ntsync/linux_ntsync.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Kernel support for NT synchronization primitive emulation
+ *
+ * Copyright (C) 2021-2022 Elizabeth Figura <zfigura@codeweavers.com>
+ */
+
+#ifndef __LINUX_NTSYNC_H
+#define __LINUX_NTSYNC_H
+
+#include <sys/types.h>
+
+typedef	uint32_t	__u32;
+typedef	uint64_t	__u64;
+
+struct linux_ntsync_sem_args {
+	__u32 count;
+	__u32 max;
+};
+
+struct linux_ntsync_mutex_args {
+	__u32 owner;
+	__u32 count;
+};
+
+struct linux_ntsync_event_args {
+	__u32 manual;
+	__u32 signaled;
+};
+
+#define LINUX_NTSYNC_WAIT_REALTIME	0x1
+
+struct linux_ntsync_wait_args {
+	__u64 timeout;
+	__u64 objs;
+	__u32 count;
+	__u32 index;
+	__u32 flags;
+	__u32 owner;
+	__u32 alert;
+	__u32 pad;
+};
+
+#define	LNTSYNC_IOC_CREATE_SEM		0x40084e80
+#define	LNTSYNC_IOC_WAIT_ANY		0xc0284e82
+#define	LNTSYNC_IOC_WAIT_ALL		0xc0284e83
+#define	LNTSYNC_IOC_CREATE_MUTEX	0x40084e84
+#define	LNTSYNC_IOC_CREATE_EVENT	0x40084e87
+#define	LNTSYNC_IOC_SEM_RELEASE		0xc0044e81
+#define	LNTSYNC_IOC_MUTEX_UNLOCK	0xc0084e85
+#define	LNTSYNC_IOC_MUTEX_KILL		0x40044e86
+#define	LNTSYNC_IOC_EVENT_SET		0x80044e88
+#define	LNTSYNC_IOC_EVENT_RESET		0x80044e89
+#define	LNTSYNC_IOC_EVENT_PULSE		0x80044e8a
+#define	LNTSYNC_IOC_SEM_READ		0x80084e8b
+#define	LNTSYNC_IOC_MUTEX_READ		0x80084e8c
+#define	LNTSYNC_IOC_EVENT_READ		0x80084e8d
+
+#define LNTSYNC_IOCTL_MIN		0x4e80
+#define LNTSYNC_IOCTL_MAX		0x4eff
+
+#endif
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 9b31035aa89d..13100cd3fe54 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -543,6 +543,7 @@ SUBDIR+=	fdt
     ${MACHINE_CPUARCH} == "i386"
 SUBDIR+=	linprocfs
 SUBDIR+=	linsysfs
+SUBDIR+=	linux_ntsync
 .endif
 .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
 SUBDIR+=	linux
diff --git a/sys/modules/linux_ntsync/Makefile b/sys/modules/linux_ntsync/Makefile
new file mode 100644
index 000000000000..4e186c5cdf4f
--- /dev/null
+++ b/sys/modules/linux_ntsync/Makefile
@@ -0,0 +1,6 @@
+.PATH: ${SRCTOP}/sys/dev/ntsync
+
+KMOD=	linux_ntsync
+SRCS=	linux_ntsync.c
+
+.include <bsd.kmod.mk>


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a1c6dbd.3efb2.7c6d34dd>