git: 1594fe0b1029 - main - linux: Add support for membarrier(2)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 22 Apr 2026 19:21:26 UTC
The branch main has been updated by pouria:
URL: https://cgit.FreeBSD.org/src/commit/?id=1594fe0b1029f246b3a14c8b21637091968362aa
commit 1594fe0b1029f246b3a14c8b21637091968362aa
Author: Ricardo Branco <rbranco@suse.de>
AuthorDate: 2026-04-18 10:11:44 +0000
Commit: Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
CommitDate: 2026-04-22 19:15:30 +0000
linux: Add support for membarrier(2)
FreeBSD has a native membarrier(2) syscall which is mostly compatible
with Linux. This is a thin wrapper around kern_membarrier() that
translates all available commands and flags.
Also update the syscalls.master prototypes to match the Linux 5.10+
three-argument form. Pre-5.10 binaries using the two-argument form
continue to work: cpu_id is only consulted for RSEQ commands, which
FreeBSD does not support and which kern_membarrier() rejects with
EINVAL, matching Linux semantics.
Signed-off-by: Ricardo Branco <rbranco@suse.de>
PR: 281691
Reviewed by: kib, pouria
Pull-Request: https://github.com/freebsd/freebsd-src/pull/2147
---
sys/amd64/linux/syscalls.master | 3 +-
sys/amd64/linux32/syscalls.master | 3 +-
sys/arm64/linux/syscalls.master | 3 +-
sys/compat/linux/linux_dummy.c | 2 --
sys/compat/linux/linux_misc.c | 64 +++++++++++++++++++++++++++++++++++++++
sys/compat/linux/linux_misc.h | 16 ++++++++++
sys/i386/linux/syscalls.master | 3 +-
7 files changed, 88 insertions(+), 6 deletions(-)
diff --git a/sys/amd64/linux/syscalls.master b/sys/amd64/linux/syscalls.master
index 5e1394751ef6..b3bbd917c013 100644
--- a/sys/amd64/linux/syscalls.master
+++ b/sys/amd64/linux/syscalls.master
@@ -1976,7 +1976,8 @@
324 AUE_NULL STD {
int linux_membarrier(
l_int cmd,
- l_int flags
+ l_uint flags,
+ l_int cpu_id
);
}
; Linux 4.4:
diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master
index 7bd522a598e8..fab68854af03 100644
--- a/sys/amd64/linux32/syscalls.master
+++ b/sys/amd64/linux32/syscalls.master
@@ -2194,7 +2194,8 @@
375 AUE_NULL STD {
int linux_membarrier(
l_int cmd,
- l_int flags
+ l_uint flags,
+ l_int cpu_id
);
}
; Linux 4.4:
diff --git a/sys/arm64/linux/syscalls.master b/sys/arm64/linux/syscalls.master
index 2babdcaf03bf..f4ab6f49c363 100644
--- a/sys/arm64/linux/syscalls.master
+++ b/sys/arm64/linux/syscalls.master
@@ -1655,7 +1655,8 @@
283 AUE_NULL STD {
int linux_membarrier(
l_int cmd,
- l_int flags
+ l_uint flags,
+ l_int cpu_id
);
}
284 AUE_NULL STD {
diff --git a/sys/compat/linux/linux_dummy.c b/sys/compat/linux/linux_dummy.c
index 46f98f4da1eb..dfabf33eb8a6 100644
--- a/sys/compat/linux/linux_dummy.c
+++ b/sys/compat/linux/linux_dummy.c
@@ -106,8 +106,6 @@ DUMMY(bpf);
DUMMY(execveat);
/* Linux 4.2: */
DUMMY(userfaultfd);
-/* Linux 4.3: */
-DUMMY(membarrier);
/* Linux 4.4: */
DUMMY(mlock2);
/* Linux 4.6: */
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 85088e8ed7ca..4c8ad669f03c 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -35,6 +35,7 @@
#include <sys/imgact.h>
#include <sys/limits.h>
#include <sys/lock.h>
+#include <sys/membarrier.h>
#include <sys/msgbuf.h>
#include <sys/mqueue.h>
#include <sys/mutex.h>
@@ -3115,4 +3116,67 @@ linux_kcmp(struct thread *td, struct linux_kcmp_args *args)
args->idx));
}
+int
+linux_membarrier(struct thread *td, struct linux_membarrier_args *args)
+{
+ static const struct {
+ int linux_cmd;
+ int freebsd_cmd;
+ } cmds[] = {
+ { LINUX_MEMBARRIER_CMD_QUERY,
+ MEMBARRIER_CMD_QUERY },
+ { LINUX_MEMBARRIER_CMD_GLOBAL,
+ MEMBARRIER_CMD_GLOBAL },
+ { LINUX_MEMBARRIER_CMD_GLOBAL_EXPEDITED,
+ MEMBARRIER_CMD_GLOBAL_EXPEDITED },
+ { LINUX_MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED,
+ MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED },
+ { LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED,
+ MEMBARRIER_CMD_PRIVATE_EXPEDITED },
+ { LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED,
+ MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED },
+ { LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE,
+ MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE },
+ { LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE,
+ MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE },
+ { LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ,
+ MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ },
+ { LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ,
+ MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ },
+ { LINUX_MEMBARRIER_CMD_GET_REGISTRATIONS,
+ MEMBARRIER_CMD_GET_REGISTRATIONS },
+ };
+ int cmd, error, flags, i, mask;
+
+ cmd = -1;
+ for (i = 0; i < nitems(cmds); i++) {
+ if (args->cmd == cmds[i].linux_cmd) {
+ cmd = cmds[i].freebsd_cmd;
+ break;
+ }
+ }
+
+ if (cmd == -1 || (args->flags & ~LINUX_MEMBARRIER_CMD_FLAG_CPU) != 0)
+ return (EINVAL);
+
+ flags = 0;
+ if ((args->flags & LINUX_MEMBARRIER_CMD_FLAG_CPU) != 0)
+ flags |= MEMBARRIER_CMD_FLAG_CPU;
+
+ error = kern_membarrier(td, cmd, flags, args->cpu_id);
+ if (error != 0)
+ return (error);
+
+ if (args->cmd == LINUX_MEMBARRIER_CMD_QUERY ||
+ args->cmd == LINUX_MEMBARRIER_CMD_GET_REGISTRATIONS) {
+ mask = td->td_retval[0];
+ td->td_retval[0] = 0;
+ for (i = 0; i < nitems(cmds); i++)
+ if ((mask & cmds[i].freebsd_cmd) != 0)
+ td->td_retval[0] |= cmds[i].linux_cmd;
+ }
+
+ return (0);
+}
+
MODULE_DEPEND(linux, mqueuefs, 1, 1, 1);
diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h
index 269fb734a69a..2044f23f30ee 100644
--- a/sys/compat/linux/linux_misc.h
+++ b/sys/compat/linux/linux_misc.h
@@ -229,4 +229,20 @@ struct syscall_info {
#define LINUX_KCMP_EPOLL_TFD 7
#define LINUX_KCMP_TYPES 8
+/* Linux membarrier commands from <linux/membarrier.h> */
+#define LINUX_MEMBARRIER_CMD_QUERY 0
+#define LINUX_MEMBARRIER_CMD_GLOBAL (1 << 0)
+#define LINUX_MEMBARRIER_CMD_GLOBAL_EXPEDITED (1 << 1)
+#define LINUX_MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED (1 << 2)
+#define LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED (1 << 3)
+#define LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED (1 << 4)
+#define LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE (1 << 5)
+#define LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE (1 << 6)
+#define LINUX_MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ (1 << 7)
+#define LINUX_MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ (1 << 8)
+#define LINUX_MEMBARRIER_CMD_GET_REGISTRATIONS (1 << 9)
+
+/* Linux membarrier flags from <linux/membarrier.h> */
+#define LINUX_MEMBARRIER_CMD_FLAG_CPU (1 << 0)
+
#endif /* _LINUX_MISC_H_ */
diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master
index 2113ea51ac5d..b93f28acae14 100644
--- a/sys/i386/linux/syscalls.master
+++ b/sys/i386/linux/syscalls.master
@@ -2206,7 +2206,8 @@
375 AUE_NULL STD {
int linux_membarrier(
l_int cmd,
- l_int flags
+ l_uint flags,
+ l_int cpu_id
);
}
; Linux 4.4: