mirror of
https://git.FreeBSD.org/src.git
synced 2026-06-02 11:24:32 +00:00
linux_ntsync: linux compat shim for ntsync(9)
Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D57038
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
.PATH: ${SRCTOP}/sys/dev/ntsync
|
||||
|
||||
KMOD= linux_ntsync
|
||||
SRCS= linux_ntsync.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
Reference in New Issue
Block a user