* [PATCH v4 0/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock()
@ 2026-07-05 17:56 André Almeida
2026-07-05 17:56 ` [PATCH v4 1/5] arm64/entry: Unify user mode handling André Almeida
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: André Almeida @ 2026-07-05 17:56 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Thomas Gleixner, Mark Rutland,
Mathieu Desnoyers, Sebastian Andrzej Siewior, Carlos O'Donell,
Peter Zijlstra, Florian Weimer, Rich Felker, Torvald Riegel,
Darren Hart, Ingo Molnar, Davidlohr Bueso, Arnd Bergmann,
Uros Bizjak, Thomas Weißschuh, Liam R. Howlett
Cc: linux-arm-kernel, linux-kernel, linux-arch, kernel-dev, LKML,
André Almeida
Hi folks,
This is my take on implementing the new vDSO for unlocking a robust futex in
arm64. If you don't know what's that, Thomas wrote a good summary,
including the motivation for this work and the x86 implementation:
https://lore.kernel.org/lkml/878qb89g7b.ffs@tglx/
* Testing
There's one selftest proposed [1] that tests precisely if the task is
interrupted during the critical section, if the kernel will clear op_pending
pointer. I've adapted to arm64 [2] and it works as expected. This test is not
being upstreamed right now because it depends on a better way to expose
vdso.so.dbg [3].
I also used gdb to manually check if the address is cleared when the kernel
interrupts the critical section.
* The patchset
As explained in the Testing section above, we developed a test that puts
breakpoints in the code to test if a user code being interrupted really clears
the op_pending pointer. This test wasn't initially working because of this check
at futex_fixup_robust_unlock():
/*
* Avoid dereferencing current->mm if not returning from interrupt.
* current->rseq.event is going to be used subsequently, so bringing the
* cache line in is not a big deal.
*/
if (!current->rseq.event.user_irq)
return;
rseq.event.user_irq was always false during my tests, and it prevents the fixup
to happen. I figured out that arm64_syscall_enter_from_user_mode() was the
issue because it doesn't set user_irq to true when the task comes from a
syscall. I dropped arm64_syscall_enter_from_user_mode() and replaced with
arm64_enter_from_user_mode() and the test now works fine. I honestly don't know
if this solution is the correct one here, so I would like to hear from the arm64
folks what's the best approach here.
Thanks!
André
[1] https://lore.kernel.org/lkml/20260404093939.7XgeW_54@linutronix.de/
[2] https://lore.kernel.org/lkml/20260529-tonyk-robust_arm-v3-3-a6f02684d4fe@igalia.com/
[3] https://lore.kernel.org/lkml/20260602090536.045586688@kernel.org/
Changes in v4:
- Added commit "arm64/entry: Unify user mode handling"
- Added missing ifdef FUTEX_ROBUST_UNLOCK guards
- Fixed the position of _start and _success labels in the critical section
- Instead of checking the zero flag, check the result register to decide if the
op_pending needs to be cleared
v3: https://patch.msgid.link/20260529-tonyk-robust_arm-v3-0-a6f02684d4fe@igalia.com
Changes in v3:
- Change asm to always use x2 to store *pop
- Fix clang asm errors
- Moved 32 bit entry point to vdso32/ and use littlearm asm
- Adapted Sebastians test for arm
v2: https://patch.msgid.link/20260424-tonyk-robust_arm-v2-0-db4e46f752cf@igalia.com
Changes in v2:
- s/CONFIG_COMPAT/CONFIG_COMPAT_VDSO (Thomas Weißschuh)
- Fixed linker not finding the symbols (Thomas Weißschuh)
v1: https://patch.msgid.link/20260417-tonyk-robust_arm-v1-0-03aa64e2ff1a@igalia.com
---
André Almeida (5):
arm64/entry: Unify user mode handling
arm64: vdso: Prepare for robust futex unlock support
arm64: vdso: Implement __vdso_futex_robust_try_unlock()
arm64: vdso32: Bring vdso32-offsets.h back
arm64: vdso32: Implement __vdso_futex_robust_try_unlock()
arch/arm64/Kconfig | 1 +
arch/arm64/Makefile | 2 +-
arch/arm64/include/asm/futex_robust.h | 19 +++++++++++++++++++
arch/arm64/include/asm/vdso.h | 3 +++
arch/arm64/kernel/entry-common.c | 11 ++---------
arch/arm64/kernel/vdso.c | 32 ++++++++++++++++++++++++++++++++
arch/arm64/kernel/vdso/Makefile | 10 ++++++++++
arch/arm64/kernel/vdso/vdso.lds.S | 9 +++++++++
arch/arm64/kernel/vdso/vfutex.c | 35 +++++++++++++++++++++++++++++++++++
arch/arm64/kernel/vdso32/Makefile | 12 ++++++++++++
arch/arm64/kernel/vdso32/vdso.lds.S | 9 +++++++++
arch/arm64/kernel/vdso32/vfutex.c | 33 +++++++++++++++++++++++++++++++++
12 files changed, 166 insertions(+), 10 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260416-tonyk-robust_arm-54ff77d2c4e4
Best regards,
--
André Almeida <andrealmeid@igalia.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4 1/5] arm64/entry: Unify user mode handling
2026-07-05 17:56 [PATCH v4 0/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock() André Almeida
@ 2026-07-05 17:56 ` André Almeida
2026-07-05 17:56 ` [PATCH v4 2/5] arm64: vdso: Prepare for robust futex unlock support André Almeida
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: André Almeida @ 2026-07-05 17:56 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Thomas Gleixner, Mark Rutland,
Mathieu Desnoyers, Sebastian Andrzej Siewior, Carlos O'Donell,
Peter Zijlstra, Florian Weimer, Rich Felker, Torvald Riegel,
Darren Hart, Ingo Molnar, Davidlohr Bueso, Arnd Bergmann,
Uros Bizjak, Thomas Weißschuh, Liam R. Howlett
Cc: linux-arm-kernel, linux-kernel, linux-arch, kernel-dev, LKML,
André Almeida
Currently, arm64 has two functions to prepare and handle context switches
from userspace: arm64_syscall_enter_from_user_mode() and
arm64_enter_from_user_mode(). The only difference is that the later calls
rseq_note_user_irq_entry() that sets rseq.event.user_irq as true.
To ensure that futex_fixup_robust_unlock() works correctly, unify the
handling from user mode functions into one that always calls
rseq_note_user_irq_entry().
Other architectures calls irqentry_enter_from_user_mode() for syscalls
and interruptions, that sets rseq.event.user_irq as well.
Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
arch/arm64/kernel/entry-common.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index ceb4eb11232a..fd62ee585b52 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -62,13 +62,6 @@ static void noinstr arm64_exit_to_kernel_mode(struct pt_regs *regs,
irqentry_exit_to_kernel_mode_after_preempt(regs, state);
}
-static __always_inline void arm64_syscall_enter_from_user_mode(struct pt_regs *regs)
-{
- enter_from_user_mode(regs);
- mte_disable_tco_entry(current);
- sme_enter_from_user_mode();
-}
-
/*
* Handle IRQ/context state management when entering from user mode.
* Before this function is called it is not safe to call regular kernel code,
@@ -729,7 +722,7 @@ static void noinstr el0_brk64(struct pt_regs *regs, unsigned long esr)
static void noinstr el0_svc(struct pt_regs *regs)
{
- arm64_syscall_enter_from_user_mode(regs);
+ arm64_enter_from_user_mode(regs);
cortex_a76_erratum_1463225_svc_handler();
fpsimd_syscall_enter();
local_daif_restore(DAIF_PROCCTX);
@@ -881,7 +874,7 @@ static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr)
static void noinstr el0_svc_compat(struct pt_regs *regs)
{
- arm64_syscall_enter_from_user_mode(regs);
+ arm64_enter_from_user_mode(regs);
cortex_a76_erratum_1463225_svc_handler();
local_daif_restore(DAIF_PROCCTX);
do_el0_svc_compat(regs);
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v4 2/5] arm64: vdso: Prepare for robust futex unlock support
2026-07-05 17:56 [PATCH v4 0/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock() André Almeida
2026-07-05 17:56 ` [PATCH v4 1/5] arm64/entry: Unify user mode handling André Almeida
@ 2026-07-05 17:56 ` André Almeida
2026-07-05 17:56 ` [PATCH v4 3/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock() André Almeida
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: André Almeida @ 2026-07-05 17:56 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Thomas Gleixner, Mark Rutland,
Mathieu Desnoyers, Sebastian Andrzej Siewior, Carlos O'Donell,
Peter Zijlstra, Florian Weimer, Rich Felker, Torvald Riegel,
Darren Hart, Ingo Molnar, Davidlohr Bueso, Arnd Bergmann,
Uros Bizjak, Thomas Weißschuh, Liam R. Howlett
Cc: linux-arm-kernel, linux-kernel, linux-arch, kernel-dev, LKML,
André Almeida
There will be a VDSO function to unlock non-contended robust futexes in
user space. The unlock sequence is racy vs. clearing the list_pending_op
pointer in the task's robust list head. To plug this race the kernel needs
to know the critical section window so it can clear the pointer when the
task is interrupted within that race window. The window is determined by
labels in the inline assembly.
Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
v4:
- Guard symbols from vdso.lds.S with ifdef
- drop update_ips() from sigpage remap function
v3:
- Fix adding vdso base addr twice
- Call vdso_futex_robust_unlock_update_ips() on remap as well
v2:
- Fixed linker not finding VDSO symbols
---
arch/arm64/kernel/vdso.c | 23 +++++++++++++++++++++++
arch/arm64/kernel/vdso/vdso.lds.S | 9 +++++++++
2 files changed, 32 insertions(+)
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 592dd8668de4..283b38684ef7 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -11,6 +11,7 @@
#include <linux/clocksource.h>
#include <linux/elf.h>
#include <linux/err.h>
+#include <linux/futex.h>
#include <linux/errno.h>
#include <linux/gfp.h>
#include <linux/kernel.h>
@@ -57,11 +58,31 @@ static struct vdso_abi_info vdso_info[] __ro_after_init = {
#endif /* CONFIG_COMPAT_VDSO */
};
+#ifdef CONFIG_FUTEX_ROBUST_UNLOCK
+static void vdso_futex_robust_unlock_update_ips(enum vdso_abi abi, struct mm_struct *mm)
+{
+ unsigned long vdso = (unsigned long) mm->context.vdso;
+ struct futex_mm_data *fd = &mm->futex;
+ uintptr_t success, end;
+
+ if (abi == VDSO_ABI_AA64) {
+ success = (uintptr_t) VDSO_SYMBOL(vdso, futex_list64_try_unlock_cs_success);
+ end = (uintptr_t) VDSO_SYMBOL(vdso, futex_list64_try_unlock_cs_end);
+
+ futex_set_vdso_cs_range(fd, 0, success, end, false);
+ }
+}
+#else
+static inline void vdso_futex_robust_unlock_update_ips(enum vdso_abi abi, struct mm_struct *mm) { }
+#endif /* CONFIG_FUTEX_ROBUST_UNLOCK */
+
static int vdso_mremap(const struct vm_special_mapping *sm,
struct vm_area_struct *new_vma)
{
current->mm->context.vdso = (void *)new_vma->vm_start;
+ vdso_futex_robust_unlock_update_ips(VDSO_ABI_AA64, current->mm);
+
return 0;
}
@@ -134,6 +155,8 @@ static int __setup_additional_pages(enum vdso_abi abi,
if (IS_ERR(ret))
goto up_fail;
+ vdso_futex_robust_unlock_update_ips(abi, mm);
+
return 0;
up_fail:
diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S
index 52314be29191..225f59bb81d1 100644
--- a/arch/arm64/kernel/vdso/vdso.lds.S
+++ b/arch/arm64/kernel/vdso/vdso.lds.S
@@ -104,6 +104,9 @@ VERSION
__kernel_clock_gettime;
__kernel_clock_getres;
__kernel_getrandom;
+#ifdef CONFIG_FUTEX_ROBUST_UNLOCK
+ __vdso_futex_robust_list64_try_unlock;
+#endif
local: *;
};
}
@@ -112,3 +115,9 @@ VERSION
* Make the sigreturn code visible to the kernel.
*/
VDSO_sigtramp = __kernel_rt_sigreturn;
+
+#ifdef CONFIG_FUTEX_ROBUST_UNLOCK
+VDSO_futex_list64_try_unlock_cs_start = __futex_list64_try_unlock_cs_start;
+VDSO_futex_list64_try_unlock_cs_success = __futex_list64_try_unlock_cs_success;
+VDSO_futex_list64_try_unlock_cs_end = __futex_list64_try_unlock_cs_end;
+#endif
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v4 3/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock()
2026-07-05 17:56 [PATCH v4 0/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock() André Almeida
2026-07-05 17:56 ` [PATCH v4 1/5] arm64/entry: Unify user mode handling André Almeida
2026-07-05 17:56 ` [PATCH v4 2/5] arm64: vdso: Prepare for robust futex unlock support André Almeida
@ 2026-07-05 17:56 ` André Almeida
2026-07-05 17:56 ` [PATCH v4 4/5] arm64: vdso32: Bring vdso32-offsets.h back André Almeida
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: André Almeida @ 2026-07-05 17:56 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Thomas Gleixner, Mark Rutland,
Mathieu Desnoyers, Sebastian Andrzej Siewior, Carlos O'Donell,
Peter Zijlstra, Florian Weimer, Rich Felker, Torvald Riegel,
Darren Hart, Ingo Molnar, Davidlohr Bueso, Arnd Bergmann,
Uros Bizjak, Thomas Weißschuh, Liam R. Howlett
Cc: linux-arm-kernel, linux-kernel, linux-arch, kernel-dev, LKML,
André Almeida
Based on the x86 implementation, implement the vDSO function for unlocking
a robust futex correctly.
Commit a2274cc0091e ("x86/vdso: Implement __vdso_futex_robust_try_unlock()")
has the full explanation about why this mechanism is needed.
The unlock assembly sequence for arm64 is:
__vdso_futex_robust_list64_try_unlock:
retry:
ldxr w8, [x0] // Load the value from *futex
cmp w1, w8 // Compare with TID
b.ne __vdso_futex_list64_try_unlock_cs_end
stlxr w3, wzr, [x0] // Try to zero *futex
__vdso_futex_list64_try_unlock_cs_start:
cbnz w3, retry
str xzr, [x2] // After zeroing *futex, zero *op_pending
__vdso_futex_list64_try_unlock_cs_end>:
The decision regarding if the pointer should be cleared or not lies on
checking the w3 register:
return (regs->user_regs[3]) ? NULL : (void __user *)
regs->user_regs.regs[2];
If it's zero, that means that the exclusive store worked and the kernel
should clear op_pending (if userspace didn't managed to) stored at x2.
Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
Notes:
- Only LL/SC for now but I can add LSE later if this looks good
v4:
- Guard makefile for vfutex.o with ifdef
- Moved _start label one instruction above
- Use results register (w3) to check for store success instead of using zero
flag
v3:
- Managed to get pop to always be stored at x2
---
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/futex_robust.h | 19 +++++++++++++++++++
arch/arm64/kernel/vdso/Makefile | 10 ++++++++++
arch/arm64/kernel/vdso/vfutex.c | 35 +++++++++++++++++++++++++++++++++++
4 files changed, 65 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b3afe0688919..0582172811d9 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -221,6 +221,7 @@ config ARM64
select HAVE_RELIABLE_STACKTRACE
select HAVE_POSIX_CPU_TIMERS_TASK_WORK
select HAVE_FUNCTION_ARG_ACCESS_API
+ select HAVE_FUTEX_ROBUST_UNLOCK
select MMU_GATHER_RCU_TABLE_FREE
select HAVE_RSEQ
select HAVE_RUST if RUSTC_SUPPORTS_ARM64
diff --git a/arch/arm64/include/asm/futex_robust.h b/arch/arm64/include/asm/futex_robust.h
new file mode 100644
index 000000000000..64f22166756a
--- /dev/null
+++ b/arch/arm64/include/asm/futex_robust.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM64_FUTEX_ROBUST_H
+#define _ASM_ARM64_FUTEX_ROBUST_H
+
+#include <asm/ptrace.h>
+
+static __always_inline void __user *arm64_futex_robust_unlock_get_pop(struct pt_regs *regs)
+{
+ /*
+ * w3 is stores the result of the stlxr instruction. If it's zero, the then
+ * the ll/sc cmpxchg succeeded and the pending op pointer needs to be cleared.
+ */
+ return (regs->user_regs.regs[3]) ? NULL : (void __user *) regs->user_regs.regs[2];
+}
+
+#define arch_futex_robust_unlock_get_pop(regs) \
+ arm64_futex_robust_unlock_get_pop(regs)
+
+#endif /* _ASM_ARM64_FUTEX_ROBUST_H */
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 7dec05dd33b7..985346c7a0bb 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -11,6 +11,10 @@ include $(srctree)/lib/vdso/Makefile.include
obj-vdso := vgettimeofday.o note.o sigreturn.o vgetrandom.o vgetrandom-chacha.o
+ifdef CONFIG_FUTEX_ROBUST_UNLOCK
+ obj-vdso += vfutex.o
+endif
+
# Build rules
targets := $(obj-vdso) vdso.so vdso.so.dbg
obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
@@ -45,9 +49,11 @@ CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables
CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_REMOVE_VDSO)
CFLAGS_REMOVE_vgetrandom.o = $(CC_FLAGS_REMOVE_VDSO)
+CFLAGS_REMOVE_vfutex.o = $(CC_FLAGS_REMOVE_VDSO)
CFLAGS_vgettimeofday.o = $(CC_FLAGS_ADD_VDSO)
CFLAGS_vgetrandom.o = $(CC_FLAGS_ADD_VDSO)
+CFLAGS_vfutex.o = $(CC_FLAGS_ADD_VDSO)
ifneq ($(c-gettimeofday-y),)
CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
@@ -57,6 +63,10 @@ ifneq ($(c-getrandom-y),)
CFLAGS_vgetrandom.o += -include $(c-getrandom-y)
endif
+ifneq ($(c-futex-y),)
+ CFLAGS_vfutex.o += -include $(c-futex-y)
+endif
+
targets += vdso.lds
CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
diff --git a/arch/arm64/kernel/vdso/vfutex.c b/arch/arm64/kernel/vdso/vfutex.c
new file mode 100644
index 000000000000..cce5ca8ce609
--- /dev/null
+++ b/arch/arm64/kernel/vdso/vfutex.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <linux/stringify.h>
+#include <vdso/futex.h>
+
+#define LABEL(name, sz) __stringify(__futex_list##sz##_try_unlock_cs_##name)
+
+#define GLOBLS(sz) ".globl " LABEL(start, sz) ", " LABEL(success, sz) ", " LABEL(end, sz) "\n"
+
+__u32 __vdso_futex_robust_list64_try_unlock(__u32 *lock, __u32 tid, __u64 *pop)
+{
+ register __u64 *pop_reg asm("x2") = pop;
+ register __u32 result_reg asm("w3") = 0;
+ __u32 val;
+
+ asm volatile (
+ GLOBLS(64)
+ " prfm pstl1strm, %[lock] \n"
+ "retry: \n"
+ " ldxr %w[val], %[lock] \n"
+ " cmp %w[tid], %w[val] \n"
+ " bne " LABEL(end, 64)" \n"
+ " stlxr %w[result], wzr, %[lock] \n"
+ LABEL(start, 64)": \n"
+ " cbnz %w[result], retry \n"
+ LABEL(success, 64)": \n"
+ " str xzr, %[pop_reg] \n"
+ LABEL(end, 64)": \n"
+
+ : [val] "=&r" (val), [result] "=&r" (result_reg)
+ : [tid] "r" (tid), [lock] "Q" (*lock), [pop_reg] "Q" (*pop_reg)
+ : "memory"
+ );
+
+ return val;
+}
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v4 4/5] arm64: vdso32: Bring vdso32-offsets.h back
2026-07-05 17:56 [PATCH v4 0/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock() André Almeida
` (2 preceding siblings ...)
2026-07-05 17:56 ` [PATCH v4 3/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock() André Almeida
@ 2026-07-05 17:56 ` André Almeida
2026-07-05 17:56 ` [PATCH v4 5/5] arm64: vdso32: Implement __vdso_futex_robust_try_unlock() André Almeida
2026-07-05 20:23 ` [PATCH v4 0/5] arm64: vdso: " Thomas Gleixner
5 siblings, 0 replies; 7+ messages in thread
From: André Almeida @ 2026-07-05 17:56 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Thomas Gleixner, Mark Rutland,
Mathieu Desnoyers, Sebastian Andrzej Siewior, Carlos O'Donell,
Peter Zijlstra, Florian Weimer, Rich Felker, Torvald Riegel,
Darren Hart, Ingo Molnar, Davidlohr Bueso, Arnd Bergmann,
Uros Bizjak, Thomas Weißschuh, Liam R. Howlett
Cc: linux-arm-kernel, linux-kernel, linux-arch, kernel-dev, LKML,
André Almeida
Commit c7767f5c43df ("arm64: vdso32: Remove unused vdso32-offsets.h")
removed vdso32-offsets.h because it was empty and therefore useless.
With the introduction of __vdso_futex_robust_try_unlock(), there is the
need to expose offsets again.
Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
arch/arm64/Makefile | 2 +-
arch/arm64/include/asm/vdso.h | 3 +++
arch/arm64/kernel/vdso32/Makefile | 8 ++++++++
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 6b005c8fef70..265716644193 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -211,7 +211,7 @@ vdso_prepare: prepare0
include/generated/vdso-offsets.h arch/arm64/kernel/vdso/vdso.so
ifdef CONFIG_COMPAT_VDSO
$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 \
- arch/arm64/kernel/vdso32/vdso.so
+ include/generated/vdso32-offsets.h arch/arm64/kernel/vdso32/vdso.so
endif
endif
diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 232b46969088..43a214b93524 100644
--- a/arch/arm64/include/asm/vdso.h
+++ b/arch/arm64/include/asm/vdso.h
@@ -10,6 +10,9 @@
#ifndef __ASSEMBLER__
#include <generated/vdso-offsets.h>
+#ifdef CONFIG_COMPAT_VDSO
+#include <generated/vdso32-offsets.h>
+#endif
#define VDSO_SYMBOL(base, name) \
({ \
diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile
index bea3675fa668..4bd60f059f4a 100644
--- a/arch/arm64/kernel/vdso32/Makefile
+++ b/arch/arm64/kernel/vdso32/Makefile
@@ -135,6 +135,14 @@ $(c-obj-vdso-gettimeofday): %.o: %.c FORCE
$(asm-obj-vdso): %.o: %.S FORCE
$(call if_changed_dep,vdsoas)
+# Generate VDSO offsets using helper script
+gen-vdsosym := $(src)/../vdso/gen_vdso_offsets.sh
+quiet_cmd_vdsosym = VDSOSYM $@
+ cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
+
+include/generated/vdso32-offsets.h: $(obj)/vdso32.so.dbg FORCE
+ $(call if_changed,vdsosym)
+
# Actual build commands
quiet_cmd_vdsold_and_vdso_check = LD32 $@
cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check)
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v4 5/5] arm64: vdso32: Implement __vdso_futex_robust_try_unlock()
2026-07-05 17:56 [PATCH v4 0/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock() André Almeida
` (3 preceding siblings ...)
2026-07-05 17:56 ` [PATCH v4 4/5] arm64: vdso32: Bring vdso32-offsets.h back André Almeida
@ 2026-07-05 17:56 ` André Almeida
2026-07-05 20:23 ` [PATCH v4 0/5] arm64: vdso: " Thomas Gleixner
5 siblings, 0 replies; 7+ messages in thread
From: André Almeida @ 2026-07-05 17:56 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Thomas Gleixner, Mark Rutland,
Mathieu Desnoyers, Sebastian Andrzej Siewior, Carlos O'Donell,
Peter Zijlstra, Florian Weimer, Rich Felker, Torvald Riegel,
Darren Hart, Ingo Molnar, Davidlohr Bueso, Arnd Bergmann,
Uros Bizjak, Thomas Weißschuh, Liam R. Howlett
Cc: linux-arm-kernel, linux-kernel, linux-arch, kernel-dev, LKML,
André Almeida
Based on aarch64 implementation, provide a 32 bit entry point for
this vDSO.
In order to keep compatibility with arm64_futex_robust_unlock_get_pop(),
make sure to store the pop address at r2 and the compare result value
at r3.
Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
arch/arm64/kernel/vdso.c | 9 +++++++++
arch/arm64/kernel/vdso32/Makefile | 4 ++++
arch/arm64/kernel/vdso32/vdso.lds.S | 9 +++++++++
arch/arm64/kernel/vdso32/vfutex.c | 33 +++++++++++++++++++++++++++++++++
4 files changed, 55 insertions(+)
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 283b38684ef7..e72a9f086999 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -71,6 +71,15 @@ static void vdso_futex_robust_unlock_update_ips(enum vdso_abi abi, struct mm_str
futex_set_vdso_cs_range(fd, 0, success, end, false);
}
+
+#ifdef CONFIG_COMPAT_VDSO
+ if (abi == VDSO_ABI_AA32) {
+ success = (uintptr_t) VDSO_SYMBOL(vdso, futex_list32_try_unlock_cs_success);
+ end = (uintptr_t) VDSO_SYMBOL(vdso, futex_list32_try_unlock_cs_end);
+
+ futex_set_vdso_cs_range(fd, 1, success, end, true);
+ }
+#endif
}
#else
static inline void vdso_futex_robust_unlock_update_ips(enum vdso_abi abi, struct mm_struct *mm) { }
diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile
index 4bd60f059f4a..f3190125c68b 100644
--- a/arch/arm64/kernel/vdso32/Makefile
+++ b/arch/arm64/kernel/vdso32/Makefile
@@ -97,6 +97,10 @@ munge := ../../../arm/vdso/vdsomunge
hostprogs := $(munge)
c-obj-vdso := note.o
+ifdef CONFIG_FUTEX_ROBUST_UNLOCK
+ c-obj-vdso += vfutex.o
+endif
+
c-obj-vdso-gettimeofday := vgettimeofday.o
ifneq ($(c-gettimeofday-y),)
diff --git a/arch/arm64/kernel/vdso32/vdso.lds.S b/arch/arm64/kernel/vdso32/vdso.lds.S
index c374fb0146f3..46c0123b2684 100644
--- a/arch/arm64/kernel/vdso32/vdso.lds.S
+++ b/arch/arm64/kernel/vdso32/vdso.lds.S
@@ -87,6 +87,15 @@ VERSION
__vdso_clock_getres;
__vdso_clock_gettime64;
__vdso_clock_getres_time64;
+#ifdef CONFIG_FUTEX_ROBUST_UNLOCK
+ __vdso_futex_robust_list32_try_unlock;
+#endif
local: *;
};
}
+
+#ifdef CONFIG_FUTEX_ROBUST_UNLOCK
+VDSO_futex_list32_try_unlock_cs_success = __futex_list32_try_unlock_cs_success;
+VDSO_futex_list32_try_unlock_cs_start = __futex_list32_try_unlock_cs_start;
+VDSO_futex_list32_try_unlock_cs_end = __futex_list32_try_unlock_cs_end;
+#endif
diff --git a/arch/arm64/kernel/vdso32/vfutex.c b/arch/arm64/kernel/vdso32/vfutex.c
new file mode 100644
index 000000000000..c47502bbe1d9
--- /dev/null
+++ b/arch/arm64/kernel/vdso32/vfutex.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <linux/stringify.h>
+#include <vdso/futex.h>
+
+#define LABEL(name, sz) __stringify(__futex_list##sz##_try_unlock_cs_##name)
+
+#define GLOBLS(sz) ".globl " LABEL(start, sz) ", " LABEL(success, sz) ", " LABEL(end, sz) "\n"
+
+__u32 __vdso_futex_robust_list32_try_unlock(__u32 *lock, __u32 tid, __u32 *pop)
+{
+ register __u32 *pop_reg asm("r2") = pop, result_reg asm("r3") = 0;
+ __u32 val, zero = 0;
+
+ asm volatile (
+ GLOBLS(32)
+ "retry: \n"
+ " ldrex %[val], %[lock] \n"
+ " cmp %[tid], %[val] \n"
+ " bne " LABEL(end, 32)" \n"
+ " strex %[result], %[zero], %[lock] \n"
+ LABEL(start, 32)": \n"
+ " cmp %[result], #0 \n"
+ " bne retry \n"
+ LABEL(success, 32)": \n"
+ " str %[zero], %[pop_reg] \n"
+ LABEL(end, 32)": \n"
+ : [val] "=&r" (val), [result] "=r" (result_reg)
+ : [tid] "r" (tid), [lock] "Q" (*lock), [pop_reg] "Q" (*pop_reg), [zero] "r" (zero)
+ : "memory"
+ );
+
+ return val;
+}
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v4 0/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock()
2026-07-05 17:56 [PATCH v4 0/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock() André Almeida
` (4 preceding siblings ...)
2026-07-05 17:56 ` [PATCH v4 5/5] arm64: vdso32: Implement __vdso_futex_robust_try_unlock() André Almeida
@ 2026-07-05 20:23 ` Thomas Gleixner
5 siblings, 0 replies; 7+ messages in thread
From: Thomas Gleixner @ 2026-07-05 20:23 UTC (permalink / raw)
To: André Almeida, Catalin Marinas, Will Deacon, Mark Rutland,
Mathieu Desnoyers, Sebastian Andrzej Siewior, Carlos O'Donell,
Peter Zijlstra, Florian Weimer, Rich Felker, Torvald Riegel,
Darren Hart, Ingo Molnar, Davidlohr Bueso, Arnd Bergmann,
Uros Bizjak, Thomas Weißschuh, Liam R. Howlett
Cc: linux-arm-kernel, linux-kernel, linux-arch, kernel-dev, LKML,
André Almeida
On Sun, Jul 05 2026 at 14:56, André Almeida wrote:
> As explained in the Testing section above, we developed a test that puts
> breakpoints in the code to test if a user code being interrupted really clears
> the op_pending pointer. This test wasn't initially working because of this check
> at futex_fixup_robust_unlock():
>
> /*
> * Avoid dereferencing current->mm if not returning from interrupt.
> * current->rseq.event is going to be used subsequently, so bringing the
> * cache line in is not a big deal.
> */
> if (!current->rseq.event.user_irq)
> return;
>
> rseq.event.user_irq was always false during my tests, and it prevents the fixup
> to happen. I figured out that arm64_syscall_enter_from_user_mode() was the
> issue because it doesn't set user_irq to true when the task comes from a
> syscall.
I have no idea what you are babbling about.
A syscall enter never sets user_irq to true. It's only set to true when
an interrupt/exception entry comes from user space, i.e. via
irqentry_enter_from_user_mode()
rseq_note_user_irq_entry()
No?
Thanks,
tglx
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-07-05 20:23 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-05 17:56 [PATCH v4 0/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock() André Almeida
2026-07-05 17:56 ` [PATCH v4 1/5] arm64/entry: Unify user mode handling André Almeida
2026-07-05 17:56 ` [PATCH v4 2/5] arm64: vdso: Prepare for robust futex unlock support André Almeida
2026-07-05 17:56 ` [PATCH v4 3/5] arm64: vdso: Implement __vdso_futex_robust_try_unlock() André Almeida
2026-07-05 17:56 ` [PATCH v4 4/5] arm64: vdso32: Bring vdso32-offsets.h back André Almeida
2026-07-05 17:56 ` [PATCH v4 5/5] arm64: vdso32: Implement __vdso_futex_robust_try_unlock() André Almeida
2026-07-05 20:23 ` [PATCH v4 0/5] arm64: vdso: " Thomas Gleixner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox