git: 510ee6698d37 - main - linux_ntsync: linux compat shim for ntsync(9)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 31 May 2026 17:19:57 UTC
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>