From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6C3F4FED3FA for ; Fri, 24 Apr 2026 18:56:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=x6Al+7ofnhtHrDKbszjhhI6yc7eZTHMI2vDoROm51NI=; b=CC3jLKrh9u67RIJ3OMjwchsOs/ 1/zUZ7ti7UhepE27OdBZ9u0ljlV4Fj6J2yqf2JpBDRoFxIqwpaoXiE3xJWfcfxKaS6OALHXnT+EwM thX6p/3psnX8sbAz3jHGLYESViQzhZYeUwgs0tfOWiCyPbLLOfuFEfaZZzyfvk83ZT1qO1Xv5WJ4x b1WocwcCq8khnfIRI4xazaUfQIyyxp9oXwK8TjWZHVJmS/VKkk1V9ezmwVDfDP1qW7Enff5jp7BX4 QFHB7BH8mNxASmNDQoa1h8KuOD9ptpfQlMw5la4v/GuTDK7Wb6egFGYyKLWEZFbA6Ih3ehrWx4vvd wfxaasCw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux)) id 1wGLhf-0000000DffH-2dUT; Fri, 24 Apr 2026 18:56:39 +0000 Received: from fanzine2.igalia.com ([213.97.179.56]) by bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1wGLhd-0000000DfeU-0c4a for linux-arm-kernel@lists.infradead.org; Fri, 24 Apr 2026 18:56:38 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=x6Al+7ofnhtHrDKbszjhhI6yc7eZTHMI2vDoROm51NI=; b=HkqbGmZB1Vmz9YB565BLp3aK3w 4KCSaXTkm2UmnKjZkf4XT/gM1u0VYdbwjXzAYwShKHk22zvLNKfddDbL/S09essorNeiuQwFSoWYv 93bjTiCR210hwVvWrPX2/VZ42C7pGOCUoXz8ABd39UAIdbdiETAf/PSM7ifjFK9p1F8DWk/jNSZXt 3ty2I2heYARgsg2hGgdrDRXFF/u/4+lT1G6eHC7Mvny2g6Y9uOROuqYur4lFMpJPRRzaGbqcJadjC udWVEtJ7br8OcuUxKZo68kV5QjvYt9EZDYLMwPZD3PIAbjVWvKfVSq5dF2dlAmLjPhJfkLts/Mi6L 1jj6UTZA==; Received: from [187.57.76.96] (helo=[192.168.15.100]) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1wGLhU-001j1m-B2; Fri, 24 Apr 2026 20:56:27 +0200 From: =?utf-8?q?Andr=C3=A9_Almeida?= Date: Fri, 24 Apr 2026 15:56:01 -0300 Subject: [PATCH RFC v2 2/2] arm64: vdso: Implement __vdso_futex_robust_try_unlock() MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Message-Id: <20260424-tonyk-robust_arm-v2-2-db4e46f752cf@igalia.com> References: <20260424-tonyk-robust_arm-v2-0-db4e46f752cf@igalia.com> In-Reply-To: <20260424-tonyk-robust_arm-v2-0-db4e46f752cf@igalia.com> 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 , "Liam R . Howlett" , Uros Bizjak , =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org, kernel-dev@igalia.com, LKML , =?utf-8?q?Andr=C3=A9_Almeida?= X-Mailer: b4 0.15.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260424_115637_367996_C98029D5 X-CRM114-Status: GOOD ( 19.42 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Based on the x86 implementation, implement the vDSO function for unlocking a robust futex correctly. Commit xxxxxxxxxxxx ("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: __futex_list64_try_unlock_cs_start: ldxr x3, [x0] // Load the value at *futex cmp x1, x3 // Compare with TID b.ne __futex_list64_try_unlock_cs_end stlxr w1, xzr, [x0] // Try to clear *futex cbnz w1, __futex_list64_try_unlock_cs_start __futex_list64_try_unlock_cs_success: str xzr, [x2] // After clearing *futex, clear *op_pending __futex_list64_try_unlock_cs_end: The decision regarding if the pointer should be cleared or not lies on checking the condition flag zero: return (regs->user_regs.pstate & PSR_Z_BIT) ? (void __user *) regs->user_regs.regs[2] : NULL; If it's not zero, that means that the comparassion worked and the kernel should clear op_pending (if userspace didn't managed to) stored at x2. Signed-off-by: André Almeida --- RFC: - Should I duplicate the explanation found in the x86 commit or can I just point to it? - Only LL/SC for now but I can add LSE later if this looks good - It the objdump I see that op_pending is store at x2. But how stable is this, how can I write it in a way that's always x2? --- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/futex_robust.h | 35 +++++++++++++ arch/arm64/kernel/vdso/Makefile | 9 +++- arch/arm64/kernel/vdso/vdso.lds.S | 4 ++ .../kernel/vdso/vfutex_robust_list_try_unlock.c | 59 ++++++++++++++++++++++ 5 files changed, 107 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 427151a9db7f..e10cb97a51c7 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -249,6 +249,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..f2b7a2b15cb5 --- /dev/null +++ b/arch/arm64/include/asm/futex_robust.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_ARM64_FUTEX_ROBUST_H +#define _ASM_ARM64_FUTEX_ROBUST_H + +#include + +static __always_inline void __user *arm64_futex_robust_unlock_get_pop(struct pt_regs *regs) +{ + /* + * RFC: According to the objdump bellow, x2 is the address of + * op_pending. How stable is this? + + <__futex_list64_try_unlock_cs_start>: + ldxr x3, [x0] + cmp x1, x3 + b.ne d7c <__futex_list64_try_unlock_cs_end> // b.any + stlxr w1, xzr, [x0] + cbnz w1, d64 <__futex_list64_try_unlock_cs_start> + + <__futex_list64_try_unlock_cs_success>: + str xzr, [x2] + + <__futex_list64_try_unlock_cs_end>: + mov w0, w3 + ret + */ + + return (regs->user_regs.pstate & PSR_Z_BIT) ? 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..a65893d8100e 100644 --- a/arch/arm64/kernel/vdso/Makefile +++ b/arch/arm64/kernel/vdso/Makefile @@ -9,7 +9,8 @@ # Include the generic Makefile to check the built vdso. include $(srctree)/lib/vdso/Makefile.include -obj-vdso := vgettimeofday.o note.o sigreturn.o vgetrandom.o vgetrandom-chacha.o +obj-vdso := vgettimeofday.o note.o sigreturn.o vgetrandom.o vgetrandom-chacha.o \ + vfutex_robust_list_try_unlock.o # Build rules targets := $(obj-vdso) vdso.so vdso.so.dbg @@ -45,9 +46,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_robust_list_try_unlock.o = $(CC_FLAGS_REMOVE_VDSO) CFLAGS_vgettimeofday.o = $(CC_FLAGS_ADD_VDSO) CFLAGS_vgetrandom.o = $(CC_FLAGS_ADD_VDSO) +CFLAGS_vfutex_robust_list_try_unlock.o = $(CC_FLAGS_ADD_VDSO) ifneq ($(c-gettimeofday-y),) CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y) @@ -57,6 +60,10 @@ ifneq ($(c-getrandom-y),) CFLAGS_vgetrandom.o += -include $(c-getrandom-y) endif +ifneq ($(c-vfutex_robust_list_try_unlock-y),) + CFLAGS_vfutex_robust_list_try_unlock.o += -include $(c-vfutex_robust_list_try_unlock-y) +endif + targets += vdso.lds CPPFLAGS_vdso.lds += -P -C -U$(ARCH) diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S index c532dae6ac8e..c324764cb6f9 100644 --- a/arch/arm64/kernel/vdso/vdso.lds.S +++ b/arch/arm64/kernel/vdso/vdso.lds.S @@ -104,6 +104,10 @@ VERSION __kernel_clock_gettime; __kernel_clock_getres; __kernel_getrandom; + __vdso_futex_robust_list64_try_unlock; +#ifdef CONFIG_COMPAT_VDSO + __vdso_futex_robust_list32_try_unlock; +#endif local: *; }; } diff --git a/arch/arm64/kernel/vdso/vfutex_robust_list_try_unlock.c b/arch/arm64/kernel/vdso/vfutex_robust_list_try_unlock.c new file mode 100644 index 000000000000..e8a8fb22a2fa --- /dev/null +++ b/arch/arm64/kernel/vdso/vfutex_robust_list_try_unlock.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include + +#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) +{ + __u32 val, result; + + asm volatile ( + GLOBLS(64) + " prfm pstl1strm, %[lock] \n" + LABEL(start, 64)": \n" + " ldxr %[val], %[lock] \n" + " cmp %[tid], %[val] \n" + " bne " LABEL(end, 64)" \n" + " stlxr %w[result], xzr, %[lock] \n" + " cbnz %w[result], " LABEL(start, 64)" \n" + LABEL(success, 64)": \n" + " str xzr, %[pop] \n" + LABEL(end, 64)": \n" + + : [val] "=&r" (val), [result] "=r" (result) + : [tid] "r" (tid), [lock] "Q" (*lock), [pop] "Q" (*pop) + : "memory" + ); + + return val; +} + +#ifdef CONFIG_COMPAT_VDSO +__u32 __vdso_futex_robust_list32_try_unlock(__u32 *lock, __u32 tid, __u32 *pop) +{ + __u32 val, result; + + asm volatile ( + GLOBLS(32) + " prfm pstl1strm, %[lock] \n" + LABEL(start, 32)": \n" + " ldxr %w[val], %[lock] \n" + " cmp %w[tid], %w[val] \n" + " bne " LABEL(end, 32)" \n" + " stlxr %w[result], wzr, %w[lock] \n" + " cbnz %w[result], " LABEL(start, 32)" \n" + LABEL(success, 32)": \n" + " str wzr, %w[pop] \n" + LABEL(end, 32)": \n" + + : [val] "=&r" (val), [result] "=r" (result) + : [tid] "r" (tid), [lock] "Q" (*lock), [pop] "Q" (*pop) + : "memory" + ); + + return val; +} +#endif -- 2.53.0