[tip: core/entry] x86/entry: Simplify the syscall number logic
From: tip-bot2 for Thomas Gleixner
Date: Sun Jul 12 2026 - 08:45:26 EST
The following commit has been merged into the core/entry branch of tip:
Commit-ID: fb419d53f2619e29bf4f96613d9a614e1c263736
Gitweb: https://git.kernel.org/tip/fb419d53f2619e29bf4f96613d9a614e1c263736
Author: Thomas Gleixner <tglx@xxxxxxxxxx>
AuthorDate: Tue, 07 Jul 2026 21:07:05 +02:00
Committer: Thomas Gleixner <tglx@xxxxxxxxxx>
CommitterDate: Sun, 12 Jul 2026 12:38:02 +02:00
x86/entry: Simplify the syscall number logic
Converting from int to long, back to int and then to unsigned int is
confusing at best.
None of this voodoo is required. Negative syscall numbers including -1
don't need any of this treatment and the low level ASM code already does
the sign extension to 64-bit on a 64-bit kernel.
The only point where signedness matters is the comparison against the
maximum syscall number, but that can be simplified by just using a unsigned
argument for the various syscall invocation functions.
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxx>
Tested-by: Mukesh Kumar Chaurasiya (IBM) <mkchauras@xxxxxxxxx>
Link: https://patch.msgid.link/20260707190254.545214398@xxxxxxxxxx
---
arch/x86/entry/syscall_32.c | 26 ++++++++++---------------
arch/x86/entry/syscall_64.c | 34 ++++++++++++---------------------
arch/x86/include/asm/syscall.h | 2 +-
3 files changed, 25 insertions(+), 37 deletions(-)
diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c
index 68e2f13..92369d8 100644
--- a/arch/x86/entry/syscall_32.c
+++ b/arch/x86/entry/syscall_32.c
@@ -41,6 +41,8 @@ const sys_call_ptr_t sys_call_table[] = {
#endif
#define __SYSCALL(nr, sym) case nr: return __ia32_##sym(regs);
+
+/* The unsigned int @nr argument is intentional as it creates denser code in a 64-bit build */
static noinline long ia32_sys_call(const struct pt_regs *regs, unsigned int nr)
{
switch (nr) {
@@ -49,7 +51,7 @@ static noinline long ia32_sys_call(const struct pt_regs *regs, unsigned int nr)
}
}
-static __always_inline int syscall_32_enter(struct pt_regs *regs)
+static __always_inline long syscall_32_enter(struct pt_regs *regs)
{
if (IS_ENABLED(CONFIG_IA32_EMULATION))
current_thread_info()->status |= TS_COMPAT;
@@ -70,17 +72,11 @@ early_param("ia32_emulation", ia32_emulation_override_cmdline);
/*
* Invoke a 32-bit syscall. Called with IRQs on in CT_STATE_KERNEL.
*/
-static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr)
+static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, unsigned long nr)
{
- /*
- * Convert negative numbers to very high and thus out of range
- * numbers for comparisons.
- */
- unsigned int unr = nr;
-
- if (likely(unr < IA32_NR_syscalls)) {
- unr = array_index_nospec(unr, IA32_NR_syscalls);
- regs->ax = ia32_sys_call(regs, unr);
+ if (likely(nr < IA32_NR_syscalls)) {
+ nr = array_index_nospec(nr, IA32_NR_syscalls);
+ regs->ax = ia32_sys_call(regs, (unsigned int)nr);
}
}
@@ -126,7 +122,7 @@ static __always_inline bool int80_is_external(void)
*/
__visible noinstr void do_int80_emulation(struct pt_regs *regs)
{
- int nr;
+ long nr;
/* Kernel does not use INT $0x80! */
if (unlikely(!user_mode(regs))) {
@@ -205,7 +201,7 @@ __visible noinstr void do_int80_emulation(struct pt_regs *regs)
*/
DEFINE_FREDENTRY_RAW(int80_emulation)
{
- int nr;
+ long nr;
enter_from_user_mode_randomize_stack(regs);
@@ -240,7 +236,7 @@ DEFINE_FREDENTRY_RAW(int80_emulation)
/* Handles int $0x80 on a 32bit kernel */
__visible noinstr void do_int80_syscall_32(struct pt_regs *regs)
{
- int nr = syscall_32_enter(regs);
+ long nr = syscall_32_enter(regs);
/*
* Subtlety here: if ptrace pokes something larger than 2^31-1 into
@@ -260,7 +256,7 @@ __visible noinstr void do_int80_syscall_32(struct pt_regs *regs)
static noinstr bool __do_fast_syscall_32(struct pt_regs *regs)
{
- int nr = syscall_32_enter(regs);
+ long nr = syscall_32_enter(regs);
int res;
enter_from_user_mode_randomize_stack(regs);
diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
index c716e0f..9a2762e 100644
--- a/arch/x86/entry/syscall_64.c
+++ b/arch/x86/entry/syscall_64.c
@@ -32,6 +32,8 @@ const sys_call_ptr_t sys_call_table[] = {
#undef __SYSCALL
#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
+
+/* The unsigned int @nr argument is intentional as it creates denser code */
static noinline long x64_sys_call(const struct pt_regs *regs, unsigned int nr)
{
switch (nr) {
@@ -52,39 +54,29 @@ static noinline long x32_sys_call(const struct pt_regs *regs, unsigned int nr)
#endif
}
-static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr)
+static __always_inline bool do_syscall_x64(struct pt_regs *regs, unsigned long nr)
{
- /*
- * Convert negative numbers to very high and thus out of range
- * numbers for comparisons.
- */
- unsigned int unr = nr;
-
- if (likely(unr < NR_syscalls)) {
- unr = array_index_nospec(unr, NR_syscalls);
- regs->ax = x64_sys_call(regs, unr);
+ if (likely(nr < NR_syscalls)) {
+ nr = array_index_nospec(nr, NR_syscalls);
+ regs->ax = x64_sys_call(regs, (unsigned int)nr);
return true;
}
return false;
}
-static __always_inline void do_syscall_x32(struct pt_regs *regs, int nr)
+static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr)
{
- /*
- * Adjust the starting offset of the table, and convert numbers
- * < __X32_SYSCALL_BIT to very high and thus out of range
- * numbers for comparisons.
- */
- unsigned int xnr = nr - __X32_SYSCALL_BIT;
+ /* Adjust the starting offset of the table */
+ nr -= __X32_SYSCALL_BIT;
- if (IS_ENABLED(CONFIG_X86_X32_ABI) && likely(xnr < X32_NR_syscalls)) {
- xnr = array_index_nospec(xnr, X32_NR_syscalls);
- regs->ax = x32_sys_call(regs, xnr);
+ if (IS_ENABLED(CONFIG_X86_X32_ABI) && likely(nr < X32_NR_syscalls)) {
+ nr = array_index_nospec(nr, X32_NR_syscalls);
+ regs->ax = x32_sys_call(regs, (unsigned int)nr);
}
}
/* Returns true to return using SYSRET, or false to use IRET */
-__visible noinstr bool do_syscall_64(struct pt_regs *regs, int nr)
+__visible noinstr bool do_syscall_64(struct pt_regs *regs, long nr)
{
nr = syscall_enter_from_user_mode_randomize_stack(regs, nr);
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
index 59a4060..cfe4251 100644
--- a/arch/x86/include/asm/syscall.h
+++ b/arch/x86/include/asm/syscall.h
@@ -164,7 +164,7 @@ static inline int syscall_get_arch(struct task_struct *task)
? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
}
-bool do_syscall_64(struct pt_regs *regs, int nr);
+bool do_syscall_64(struct pt_regs *regs, long nr);
void do_int80_emulation(struct pt_regs *regs);
#endif /* CONFIG_X86_32 */