linux-user/syscall.c | 9 +++++++++ linux-user/syscall_defs.h | 4 ++++ 2 files changed, 13 insertions(+)
TARGET_NR_mlock2 is defined for every target's syscall table (it has
been available on all Linux architectures since it was added in
kernel 4.4), and linux-user/strace.list already has an entry for it,
but linux-user/syscall.c has no case handler for it. A guest mlock2()
call therefore falls through to the default case and gets -ENOSYS
instead of being emulated, on every target.
mlock2() differs from mlock() only by a third `flags` argument
(MLOCK_ONFAULT). Add TARGET_MLOCK_ONFAULT and a case that validates
the flags argument and forwards to the host mlock2(), mirroring the
existing TARGET_NR_mlock case immediately above it.
Signed-off-by: Michael Morrell <mmorrell@tachyum.com>
---
linux-user/syscall.c | 9 +++++++++
linux-user/syscall_defs.h | 4 ++++
2 files changed, 13 insertions(+)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index cfa68dfbdb..9f454502cb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -11230,6 +11230,15 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
case TARGET_NR_mlock:
return get_errno(mlock(g2h(cpu, arg1), arg2));
#endif
+#ifdef TARGET_NR_mlock2
+ case TARGET_NR_mlock2:
+ if (arg3 & ~TARGET_MLOCK_ONFAULT) {
+ return -TARGET_EINVAL;
+ }
+ return get_errno(mlock2(g2h(cpu, arg1), arg2,
+ (arg3 & TARGET_MLOCK_ONFAULT) ?
+ MLOCK_ONFAULT : 0));
+#endif
#ifdef TARGET_NR_munlock
case TARGET_NR_munlock:
return get_errno(munlock(g2h(cpu, arg1), arg2));
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index e28853c93b..f5831a6bad 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -2795,6 +2795,10 @@ struct target_mount_attr_ver0 {
#ifndef RESOLVE_IN_ROOT
#define RESOLVE_IN_ROOT 0x10
#endif
+
+/* flags for mlock2() */
+#define TARGET_MLOCK_ONFAULT 0x01
+
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
(defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
defined(TARGET_M68K) || defined(TARGET_MICROBLAZE) || \
--
2.43.0
ping
-----Original Message-----
From: Michael Morrell <mmorrell@tachyum.com>
Sent: Monday, September 14, 2026 4:32 PM
To: qemu-devel@nongnu.org
Cc: Laurent Vivier <laurent@vivier.eu>; Helge Deller <deller@gmx.de>; Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>; Michael Morrell <mmorrell@tachyum.com>
Subject: [PATCH v2] linux-user: implement mlock2(2) syscall
TARGET_NR_mlock2 is defined for every target's syscall table (it has been available on all Linux architectures since it was added in kernel 4.4), and linux-user/strace.list already has an entry for it, but linux-user/syscall.c has no case handler for it. A guest mlock2() call therefore falls through to the default case and gets -ENOSYS instead of being emulated, on every target.
mlock2() differs from mlock() only by a third `flags` argument (MLOCK_ONFAULT). Add TARGET_MLOCK_ONFAULT and a case that validates the flags argument and forwards to the host mlock2(), mirroring the existing TARGET_NR_mlock case immediately above it.
Signed-off-by: Michael Morrell <mmorrell@tachyum.com>
---
linux-user/syscall.c | 9 +++++++++
linux-user/syscall_defs.h | 4 ++++
2 files changed, 13 insertions(+)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cfa68dfbdb..9f454502cb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -11230,6 +11230,15 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
case TARGET_NR_mlock:
return get_errno(mlock(g2h(cpu, arg1), arg2)); #endif
+#ifdef TARGET_NR_mlock2
+ case TARGET_NR_mlock2:
+ if (arg3 & ~TARGET_MLOCK_ONFAULT) {
+ return -TARGET_EINVAL;
+ }
+ return get_errno(mlock2(g2h(cpu, arg1), arg2,
+ (arg3 & TARGET_MLOCK_ONFAULT) ?
+ MLOCK_ONFAULT : 0)); #endif
#ifdef TARGET_NR_munlock
case TARGET_NR_munlock:
return get_errno(munlock(g2h(cpu, arg1), arg2)); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index e28853c93b..f5831a6bad 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -2795,6 +2795,10 @@ struct target_mount_attr_ver0 { #ifndef RESOLVE_IN_ROOT
#define RESOLVE_IN_ROOT 0x10
#endif
+
+/* flags for mlock2() */
+#define TARGET_MLOCK_ONFAULT 0x01
+
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
(defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
defined(TARGET_M68K) || defined(TARGET_MICROBLAZE) || \
--
2.43.0
On 9/22/26 22:14, Michael Morrell wrote:
> ping
has been merged upstream already:
https://gitlab.com/qemu-project/qemu/-/commit/30fa3eb41f85e114765e8476dc9a32a890b2e78f
Helge
> -----Original Message-----
> From: Michael Morrell <mmorrell@tachyum.com>
> Sent: Monday, September 14, 2026 4:32 PM
> To: qemu-devel@nongnu.org
> Cc: Laurent Vivier <laurent@vivier.eu>; Helge Deller <deller@gmx.de>; Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>; Michael Morrell <mmorrell@tachyum.com>
> Subject: [PATCH v2] linux-user: implement mlock2(2) syscall
>
> TARGET_NR_mlock2 is defined for every target's syscall table (it has been available on all Linux architectures since it was added in kernel 4.4), and linux-user/strace.list already has an entry for it, but linux-user/syscall.c has no case handler for it. A guest mlock2() call therefore falls through to the default case and gets -ENOSYS instead of being emulated, on every target.
>
> mlock2() differs from mlock() only by a third `flags` argument (MLOCK_ONFAULT). Add TARGET_MLOCK_ONFAULT and a case that validates the flags argument and forwards to the host mlock2(), mirroring the existing TARGET_NR_mlock case immediately above it.
>
> Signed-off-by: Michael Morrell <mmorrell@tachyum.com>
> ---
> linux-user/syscall.c | 9 +++++++++
> linux-user/syscall_defs.h | 4 ++++
> 2 files changed, 13 insertions(+)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cfa68dfbdb..9f454502cb 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -11230,6 +11230,15 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
> case TARGET_NR_mlock:
> return get_errno(mlock(g2h(cpu, arg1), arg2)); #endif
> +#ifdef TARGET_NR_mlock2
> + case TARGET_NR_mlock2:
> + if (arg3 & ~TARGET_MLOCK_ONFAULT) {
> + return -TARGET_EINVAL;
> + }
> + return get_errno(mlock2(g2h(cpu, arg1), arg2,
> + (arg3 & TARGET_MLOCK_ONFAULT) ?
> + MLOCK_ONFAULT : 0)); #endif
> #ifdef TARGET_NR_munlock
> case TARGET_NR_munlock:
> return get_errno(munlock(g2h(cpu, arg1), arg2)); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index e28853c93b..f5831a6bad 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -2795,6 +2795,10 @@ struct target_mount_attr_ver0 { #ifndef RESOLVE_IN_ROOT
> #define RESOLVE_IN_ROOT 0x10
> #endif
> +
> +/* flags for mlock2() */
> +#define TARGET_MLOCK_ONFAULT 0x01
> +
> #if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
> (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
> defined(TARGET_M68K) || defined(TARGET_MICROBLAZE) || \
> --
> 2.43.0
>
>
>
© 2016 - 2026 Red Hat, Inc.