From: "H. Peter Anvin" <hpa@zytor.com>
To: "H. Peter Anvin" <hpa@zytor.com>,
"Jason A. Donenfeld" <Jason@zx2c4.com>,
"Peter Zijlstra (Intel)" <peterz@infradead.org>,
"Theodore Ts'o" <tytso@mit.edu>,
"Thomas Weißschuh" <thomas.weissschuh@linutronix.de>,
"Xin Li" <xin@zytor.com>,
"Andrew Cooper" <andrew.cooper3@citrix.com>,
"Andy Lutomirski" <luto@kernel.org>,
"Ard Biesheuvel" <ardb@kernel.org>,
"Borislav Petkov" <bp@alien8.de>,
"Brian Gerst" <brgerst@gmail.com>,
"Dave Hansen" <dave.hansen@linux.intel.com>,
"Ingo Molnar" <mingo@redhat.com>,
"James Morse" <james.morse@arm.com>,
"Jarkko Sakkinen" <jarkko@kernel.org>,
"Josh Poimboeuf" <jpoimboe@kernel.org>,
"Kees Cook" <kees@kernel.org>, "Nam Cao" <namcao@linutronix.de>,
"Oleg Nesterov" <oleg@redhat.com>,
"Perry Yuan" <perry.yuan@amd.com>,
"Thomas Gleixner" <tglx@linutronix.de>,
"Thomas Huth" <thuth@redhat.com>,
"Uros Bizjak" <ubizjak@gmail.com>,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-sgx@vger.kernel.org, x86@kernel.org
Subject: [PATCH v3 7/9] x86/vdso: abstract out vdso system call internals
Date: Wed, 12 Nov 2025 12:22:52 -0800 [thread overview]
Message-ID: <20251112202258.1310754-8-hpa@zytor.com> (raw)
In-Reply-To: <20251112202258.1310754-1-hpa@zytor.com>
Abstract out the calling of true system calls from the vdso into
macros.
It has been a very long time since gcc did not allow %ebx or %ebp in
inline asm in 32-bit PIC mode; remove the corresponding hacks.
Remove the use of memory output constraints in gettimeofday.h in favor
of "memory" clobbers. The resulting code is identical for the current
use cases, as the system call is usually a terminal fallback anyway,
and it merely complicates the macroization.
This patch adds only a handful of more lines of code than it removes,
and in fact could be made substantially smaller by removing the macros
for the argument counts that aren't currently used, however, it seems
better to be general from the start.
[ v3: remove stray comment from prototyping; remove VDSO_SYSCALL6()
since it would require special handling on 32 bits and is
currently unused. (Uros Biszjak)
Indent nested preprocessor directives. ]
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
---
arch/x86/include/asm/vdso/gettimeofday.h | 108 ++---------------------
arch/x86/include/asm/vdso/sys_call.h | 103 +++++++++++++++++++++
2 files changed, 111 insertions(+), 100 deletions(-)
create mode 100644 arch/x86/include/asm/vdso/sys_call.h
diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h
index 73b2e7ee8f0f..3cf214cc4a75 100644
--- a/arch/x86/include/asm/vdso/gettimeofday.h
+++ b/arch/x86/include/asm/vdso/gettimeofday.h
@@ -18,6 +18,7 @@
#include <asm/msr.h>
#include <asm/pvclock.h>
#include <clocksource/hyperv_timer.h>
+#include <asm/vdso/sys_call.h>
#define VDSO_HAS_TIME 1
@@ -53,130 +54,37 @@ extern struct ms_hyperv_tsc_page hvclock_page
__attribute__((visibility("hidden")));
#endif
-#ifndef BUILD_VDSO32
-
static __always_inline
long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
{
- long ret;
-
- asm ("syscall" : "=a" (ret), "=m" (*_ts) :
- "0" (__NR_clock_gettime), "D" (_clkid), "S" (_ts) :
- "rcx", "r11");
-
- return ret;
+ return VDSO_SYSCALL2(clock_gettime,64,_clkid,_ts);
}
static __always_inline
long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
struct timezone *_tz)
{
- long ret;
-
- asm("syscall" : "=a" (ret) :
- "0" (__NR_gettimeofday), "D" (_tv), "S" (_tz) : "memory");
-
- return ret;
+ return VDSO_SYSCALL2(gettimeofday,,_tv,_tz);
}
static __always_inline
long clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
{
- long ret;
-
- asm ("syscall" : "=a" (ret), "=m" (*_ts) :
- "0" (__NR_clock_getres), "D" (_clkid), "S" (_ts) :
- "rcx", "r11");
-
- return ret;
+ return VDSO_SYSCALL2(clock_getres,_time64,_clkid,_ts);
}
-#else
-
-static __always_inline
-long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
-{
- long ret;
-
- asm (
- "mov %%ebx, %%edx \n"
- "mov %[clock], %%ebx \n"
- "call __kernel_vsyscall \n"
- "mov %%edx, %%ebx \n"
- : "=a" (ret), "=m" (*_ts)
- : "0" (__NR_clock_gettime64), [clock] "g" (_clkid), "c" (_ts)
- : "edx");
-
- return ret;
-}
+#ifndef CONFIG_X86_64
static __always_inline
long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
{
- long ret;
-
- asm (
- "mov %%ebx, %%edx \n"
- "mov %[clock], %%ebx \n"
- "call __kernel_vsyscall \n"
- "mov %%edx, %%ebx \n"
- : "=a" (ret), "=m" (*_ts)
- : "0" (__NR_clock_gettime), [clock] "g" (_clkid), "c" (_ts)
- : "edx");
-
- return ret;
-}
-
-static __always_inline
-long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
- struct timezone *_tz)
-{
- long ret;
-
- asm(
- "mov %%ebx, %%edx \n"
- "mov %2, %%ebx \n"
- "call __kernel_vsyscall \n"
- "mov %%edx, %%ebx \n"
- : "=a" (ret)
- : "0" (__NR_gettimeofday), "g" (_tv), "c" (_tz)
- : "memory", "edx");
-
- return ret;
+ return VDSO_SYSCALL2(clock_gettime,,_clkid,_ts);
}
static __always_inline long
-clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
-{
- long ret;
-
- asm (
- "mov %%ebx, %%edx \n"
- "mov %[clock], %%ebx \n"
- "call __kernel_vsyscall \n"
- "mov %%edx, %%ebx \n"
- : "=a" (ret), "=m" (*_ts)
- : "0" (__NR_clock_getres_time64), [clock] "g" (_clkid), "c" (_ts)
- : "edx");
-
- return ret;
-}
-
-static __always_inline
-long clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
{
- long ret;
-
- asm (
- "mov %%ebx, %%edx \n"
- "mov %[clock], %%ebx \n"
- "call __kernel_vsyscall \n"
- "mov %%edx, %%ebx \n"
- : "=a" (ret), "=m" (*_ts)
- : "0" (__NR_clock_getres), [clock] "g" (_clkid), "c" (_ts)
- : "edx");
-
- return ret;
+ return VDSO_SYSCALL2(clock_getres,,_clkid,_ts);
}
#endif
diff --git a/arch/x86/include/asm/vdso/sys_call.h b/arch/x86/include/asm/vdso/sys_call.h
new file mode 100644
index 000000000000..dcfd17c6dd57
--- /dev/null
+++ b/arch/x86/include/asm/vdso/sys_call.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Macros for issuing an inline system call from the vDSO.
+ */
+
+#ifndef X86_ASM_VDSO_SYS_CALL_H
+#define X86_ASM_VDSO_SYS_CALL_H
+
+#include <linux/compiler.h>
+#include <asm/cpufeatures.h>
+#include <asm/alternative.h>
+
+#ifdef CONFIG_X86_64
+# define __sys_instr "syscall"
+# define __sys_clobber "rcx", "r11", "memory"
+# define __sys_nr(x,y) __NR_ ## x
+# define __sys_reg1 "rdi"
+# define __sys_reg2 "rsi"
+# define __sys_reg3 "rdx"
+# define __sys_reg4 "r10"
+# define __sys_reg5 "r8"
+#else
+# define __sys_instr "call __kernel_vsyscall"
+# define __sys_clobber "memory"
+# define __sys_nr(x,y) __NR_ ## x ## y
+# define __sys_reg1 "ebx"
+# define __sys_reg2 "ecx"
+# define __sys_reg3 "edx"
+# define __sys_reg4 "esi"
+# define __sys_reg5 "edi"
+#endif
+
+/*
+ * Example usage:
+ *
+ * result = VDSO_SYSCALL3(foo,64,x,y,z);
+ *
+ * ... calls foo(x,y,z) on 64 bits, and foo64(x,y,z) on 32 bits.
+ *
+ * VDSO_SYSCALL6() is currently missing, because it would require
+ * special handling for %ebp on 32 bits when the vdso is compiled with
+ * frame pointers enabled (the default on 32 bits.) Add it as a special
+ * case when and if it becomes necessary.
+ */
+#define _VDSO_SYSCALL(name,suf32,...) \
+ ({ \
+ long _sys_num_ret = __sys_nr(name,suf32); \
+ asm_inline volatile( \
+ __sys_instr \
+ : "+a" (_sys_num_ret) \
+ : __VA_ARGS__ \
+ : __sys_clobber); \
+ _sys_num_ret; \
+ })
+
+#define VDSO_SYSCALL0(name,suf32) \
+ _VDSO_SYSCALL(name,suf32)
+#define VDSO_SYSCALL1(name,suf32,a1) \
+ ({ \
+ register long _sys_arg1 asm(__sys_reg1) = (long)(a1); \
+ _VDSO_SYSCALL(name,suf32, \
+ "r" (_sys_arg1)); \
+ })
+#define VDSO_SYSCALL2(name,suf32,a1,a2) \
+ ({ \
+ register long _sys_arg1 asm(__sys_reg1) = (long)(a1); \
+ register long _sys_arg2 asm(__sys_reg2) = (long)(a2); \
+ _VDSO_SYSCALL(name,suf32, \
+ "r" (_sys_arg1), "r" (_sys_arg2)); \
+ })
+#define VDSO_SYSCALL3(name,suf32,a1,a2,a3) \
+ ({ \
+ register long _sys_arg1 asm(__sys_reg1) = (long)(a1); \
+ register long _sys_arg2 asm(__sys_reg2) = (long)(a2); \
+ register long _sys_arg3 asm(__sys_reg3) = (long)(a3); \
+ _VDSO_SYSCALL(name,suf32, \
+ "r" (_sys_arg1), "r" (_sys_arg2), \
+ "r" (_sys_arg3)); \
+ })
+#define VDSO_SYSCALL4(name,suf32,a1,a2,a3,a4) \
+ ({ \
+ register long _sys_arg1 asm(__sys_reg1) = (long)(a1); \
+ register long _sys_arg2 asm(__sys_reg2) = (long)(a2); \
+ register long _sys_arg3 asm(__sys_reg3) = (long)(a3); \
+ register long _sys_arg4 asm(__sys_reg4) = (long)(a4); \
+ _VDSO_SYSCALL(name,suf32, \
+ "r" (_sys_arg1), "r" (_sys_arg2), \
+ "r" (_sys_arg3), "r" (_sys_arg4)); \
+ })
+#define VDSO_SYSCALL5(name,suf32,a1,a2,a3,a4,a5) \
+ ({ \
+ register long _sys_arg1 asm(__sys_reg1) = (long)(a1); \
+ register long _sys_arg2 asm(__sys_reg2) = (long)(a2); \
+ register long _sys_arg3 asm(__sys_reg3) = (long)(a3); \
+ register long _sys_arg4 asm(__sys_reg4) = (long)(a4); \
+ register long _sys_arg5 asm(__sys_reg5) = (long)(a5); \
+ _VDSO_SYSCALL(name,suf32, \
+ "r" (_sys_arg1), "r" (_sys_arg2), \
+ "r" (_sys_arg3), "r" (_sys_arg4), \
+ "r" (_sys_arg5)); \
+ })
+
+#endif /* X86_VDSO_SYS_CALL_H */
--
2.51.1
next prev parent reply other threads:[~2025-11-12 20:23 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-12 20:22 [PATCH v3 0/9] x86/entry/vdso: clean up the vdso build, vdso updates H. Peter Anvin
2025-11-12 20:22 ` [PATCH v3 1/9] x86/entry/vdso: rename vdso_image_* to vdso*_image H. Peter Anvin
2025-11-13 19:31 ` Andrew Cooper
2025-11-12 20:22 ` [PATCH v3 2/9] x86/entry/vdso: refactor the vdso build H. Peter Anvin
2025-11-13 18:38 ` Brian Gerst
2025-11-13 21:11 ` H. Peter Anvin
2025-11-13 22:41 ` Brian Gerst
2025-11-12 20:22 ` [PATCH v3 3/9] x86/entry/vdso32: don't rely on int80_landing_pad for adjusting ip H. Peter Anvin
2025-11-12 20:22 ` [PATCH v3 4/9] x86/entry/vdso32: remove SYSCALL_ENTER_KERNEL macro in sigreturn.S H. Peter Anvin
2025-11-12 20:22 ` [PATCH v3 5/9] x86/entry/vdso32: remove open-coded DWARF " H. Peter Anvin
2025-11-12 20:22 ` [PATCH v3 6/9] x86/entry/vdso: include GNU_PROPERTY and GNU_STACK PHDRs H. Peter Anvin
2025-11-13 19:09 ` Andrew Cooper
2025-11-13 21:13 ` H. Peter Anvin
2025-11-12 20:22 ` H. Peter Anvin [this message]
2025-11-12 20:22 ` [PATCH v3 8/9] x86/cpufeature: replace X86_FEATURE_SYSENTER32 with X86_FEATURE_SYSFAST32 H. Peter Anvin
2025-11-12 20:22 ` [PATCH v3 9/9] x86/entry/vdso32: when using int $0x80, use it directly H. Peter Anvin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251112202258.1310754-8-hpa@zytor.com \
--to=hpa@zytor.com \
--cc=Jason@zx2c4.com \
--cc=andrew.cooper3@citrix.com \
--cc=ardb@kernel.org \
--cc=bp@alien8.de \
--cc=brgerst@gmail.com \
--cc=dave.hansen@linux.intel.com \
--cc=james.morse@arm.com \
--cc=jarkko@kernel.org \
--cc=jpoimboe@kernel.org \
--cc=kees@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-sgx@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@redhat.com \
--cc=namcao@linutronix.de \
--cc=oleg@redhat.com \
--cc=perry.yuan@amd.com \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=thomas.weissschuh@linutronix.de \
--cc=thuth@redhat.com \
--cc=tytso@mit.edu \
--cc=ubizjak@gmail.com \
--cc=x86@kernel.org \
--cc=xin@zytor.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox