The branch main has been updated by kib:

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

commit 510ee6698d377f4a9a4eeb08d9dc17bdc72ad5ab
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-05-19 02:23:33 +0000
Commit:     Konstantin Belousov <[email protected]>
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 <[email protected]>
+ * 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 <[email protected]>
+ */
+
+#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>

Reply via email to