]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tools/nolibc: handle 64-bit system call arguments on MIPS N32
authorThomas Weißschuh <linux@weissschuh.net>
Sat, 18 Apr 2026 10:20:00 +0000 (12:20 +0200)
committerThomas Weißschuh <linux@weissschuh.net>
Mon, 27 Apr 2026 18:09:07 +0000 (20:09 +0200)
The N32 system call ABI expects 64-bit values directly in registers.
This does not work on nolibc currently, as a 'long' is only 32 bits
wide. Switch the system call wrappers to use 'long long' instead which
can handle 64-bit values on N32. As on N64 'long' and 'long long' are
the same, this does not change the behavior there.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Acked-by: Willy Tarreau <w@1wt.eu>
Link: https://patch.msgid.link/20260418-nolibc-largefile-v1-5-b91f0775bac3@weissschuh.net
tools/include/nolibc/arch-mips.h

index 2b7a0bd3fc30fe45504229ec980b778c59972d3b..1400653c76c1e691a736f1e6be0d8e5f395df16a 100644 (file)
@@ -55,6 +55,8 @@
 #define _NOLIBC_SYSCALL_STACK_RESERVE "addiu $sp, $sp, -32\n"
 #define _NOLIBC_SYSCALL_STACK_UNRESERVE "addiu $sp, $sp, 32\n"
 
+#define _NOLIBC_SYSCALL_REG register long
+
 #else /* _ABIN32 || _ABI64 */
 
 /* binutils, GCC and clang disagree about register aliases, use numbers instead. */
 #define _NOLIBC_SYSCALL_STACK_RESERVE
 #define _NOLIBC_SYSCALL_STACK_UNRESERVE
 
+#define _NOLIBC_SYSCALL_REG register long long
+
 #endif /* _ABIO32 */
 
 #define __nolibc_syscall0(num)                                                \
 ({                                                                            \
-       register long _num __asm__ ("v0") = (num);                            \
-       register long _arg4 __asm__ ("a3");                                   \
+       _NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \
+       _NOLIBC_SYSCALL_REG _arg4 __asm__ ("a3");                             \
                                                                              \
        __asm__ volatile (                                                    \
                _NOLIBC_SYSCALL_STACK_RESERVE                                 \
@@ -86,9 +90,9 @@
 
 #define __nolibc_syscall1(num, arg1)                                          \
 ({                                                                            \
-       register long _num __asm__ ("v0") = (num);                            \
-       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
-       register long _arg4 __asm__ ("a3");                                   \
+       _NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \
+       _NOLIBC_SYSCALL_REG _arg1 __asm__ ("a0") = __nolibc_arg_to_reg(arg1); \
+       _NOLIBC_SYSCALL_REG _arg4 __asm__ ("a3");                             \
                                                                              \
        __asm__ volatile (                                                    \
                _NOLIBC_SYSCALL_STACK_RESERVE                                 \
 
 #define __nolibc_syscall2(num, arg1, arg2)                                    \
 ({                                                                            \
-       register long _num __asm__ ("v0") = (num);                            \
-       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
-       register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
-       register long _arg4 __asm__ ("a3");                                   \
+       _NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \
+       _NOLIBC_SYSCALL_REG _arg1 __asm__ ("a0") = __nolibc_arg_to_reg(arg1); \
+       _NOLIBC_SYSCALL_REG _arg2 __asm__ ("a1") = __nolibc_arg_to_reg(arg2); \
+       _NOLIBC_SYSCALL_REG _arg4 __asm__ ("a3");                             \
                                                                              \
        __asm__ volatile (                                                    \
                _NOLIBC_SYSCALL_STACK_RESERVE                                 \
 
 #define __nolibc_syscall3(num, arg1, arg2, arg3)                              \
 ({                                                                            \
-       register long _num __asm__ ("v0")  = (num);                           \
-       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
-       register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
-       register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
-       register long _arg4 __asm__ ("a3");                                   \
+       _NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \
+       _NOLIBC_SYSCALL_REG _arg1 __asm__ ("a0") = __nolibc_arg_to_reg(arg1); \
+       _NOLIBC_SYSCALL_REG _arg2 __asm__ ("a1") = __nolibc_arg_to_reg(arg2); \
+       _NOLIBC_SYSCALL_REG _arg3 __asm__ ("a2") = __nolibc_arg_to_reg(arg3); \
+       _NOLIBC_SYSCALL_REG _arg4 __asm__ ("a3");                             \
                                                                              \
        __asm__ volatile (                                                    \
                _NOLIBC_SYSCALL_STACK_RESERVE                                 \
 
 #define __nolibc_syscall4(num, arg1, arg2, arg3, arg4)                        \
 ({                                                                            \
-       register long _num __asm__ ("v0") = (num);                            \
-       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
-       register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
-       register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
-       register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
+       _NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \
+       _NOLIBC_SYSCALL_REG _arg1 __asm__ ("a0") = __nolibc_arg_to_reg(arg1); \
+       _NOLIBC_SYSCALL_REG _arg2 __asm__ ("a1") = __nolibc_arg_to_reg(arg2); \
+       _NOLIBC_SYSCALL_REG _arg3 __asm__ ("a2") = __nolibc_arg_to_reg(arg3); \
+       _NOLIBC_SYSCALL_REG _arg4 __asm__ ("a3") = __nolibc_arg_to_reg(arg4); \
                                                                              \
        __asm__ volatile (                                                    \
                _NOLIBC_SYSCALL_STACK_RESERVE                                 \
 
 #define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5)                  \
 ({                                                                            \
-       register long _num __asm__ ("v0") = (num);                            \
-       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
-       register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
-       register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
-       register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
-       register long _arg5 = (long)(arg5);                                   \
+       _NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \
+       _NOLIBC_SYSCALL_REG _arg1 __asm__ ("a0") = __nolibc_arg_to_reg(arg1); \
+       _NOLIBC_SYSCALL_REG _arg2 __asm__ ("a1") = __nolibc_arg_to_reg(arg2); \
+       _NOLIBC_SYSCALL_REG _arg3 __asm__ ("a2") = __nolibc_arg_to_reg(arg3); \
+       _NOLIBC_SYSCALL_REG _arg4 __asm__ ("a3") = __nolibc_arg_to_reg(arg4); \
+       _NOLIBC_SYSCALL_REG _arg5 = __nolibc_arg_to_reg(arg5);                \
                                                                              \
        __asm__ volatile (                                                    \
                _NOLIBC_SYSCALL_STACK_RESERVE                                 \
 
 #define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)            \
 ({                                                                            \
-       register long _num __asm__ ("v0")  = (num);                           \
-       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
-       register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
-       register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
-       register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
-       register long _arg5 = (long)(arg5);                                   \
-       register long _arg6 = (long)(arg6);                                   \
+       _NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \
+       _NOLIBC_SYSCALL_REG _arg1 __asm__ ("a0") = __nolibc_arg_to_reg(arg1); \
+       _NOLIBC_SYSCALL_REG _arg2 __asm__ ("a1") = __nolibc_arg_to_reg(arg2); \
+       _NOLIBC_SYSCALL_REG _arg3 __asm__ ("a2") = __nolibc_arg_to_reg(arg3); \
+       _NOLIBC_SYSCALL_REG _arg4 __asm__ ("a3") = __nolibc_arg_to_reg(arg4); \
+       _NOLIBC_SYSCALL_REG _arg5 = __nolibc_arg_to_reg(arg5);                \
+       _NOLIBC_SYSCALL_REG _arg6 = __nolibc_arg_to_reg(arg6);                \
                                                                              \
        __asm__ volatile (                                                    \
                _NOLIBC_SYSCALL_STACK_RESERVE                                 \
 
 #define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5)                  \
 ({                                                                            \
-       register long _num __asm__ ("v0") = (num);                            \
-       register long _arg1 __asm__ ("$4") = (long)(arg1);                    \
-       register long _arg2 __asm__ ("$5") = (long)(arg2);                    \
-       register long _arg3 __asm__ ("$6") = (long)(arg3);                    \
-       register long _arg4 __asm__ ("$7") = (long)(arg4);                    \
-       register long _arg5 __asm__ ("$8") = (long)(arg5);                    \
+       _NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \
+       _NOLIBC_SYSCALL_REG _arg1 __asm__ ("$4") = __nolibc_arg_to_reg(arg1); \
+       _NOLIBC_SYSCALL_REG _arg2 __asm__ ("$5") = __nolibc_arg_to_reg(arg2); \
+       _NOLIBC_SYSCALL_REG _arg3 __asm__ ("$6") = __nolibc_arg_to_reg(arg3); \
+       _NOLIBC_SYSCALL_REG _arg4 __asm__ ("$7") = __nolibc_arg_to_reg(arg4); \
+       _NOLIBC_SYSCALL_REG _arg5 __asm__ ("$8") = __nolibc_arg_to_reg(arg5); \
                                                                              \
        __asm__ volatile (                                                    \
                "syscall\n"                                                   \
 
 #define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)            \
 ({                                                                            \
-       register long _num __asm__ ("v0")  = (num);                           \
-       register long _arg1 __asm__ ("$4") = (long)(arg1);                    \
-       register long _arg2 __asm__ ("$5") = (long)(arg2);                    \
-       register long _arg3 __asm__ ("$6") = (long)(arg3);                    \
-       register long _arg4 __asm__ ("$7") = (long)(arg4);                    \
-       register long _arg5 __asm__ ("$8") = (long)(arg5);                    \
-       register long _arg6 __asm__ ("$9") = (long)(arg6);                    \
+       _NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \
+       _NOLIBC_SYSCALL_REG _arg1 __asm__ ("$4") = __nolibc_arg_to_reg(arg1); \
+       _NOLIBC_SYSCALL_REG _arg2 __asm__ ("$5") = __nolibc_arg_to_reg(arg2); \
+       _NOLIBC_SYSCALL_REG _arg3 __asm__ ("$6") = __nolibc_arg_to_reg(arg3); \
+       _NOLIBC_SYSCALL_REG _arg4 __asm__ ("$7") = __nolibc_arg_to_reg(arg4); \
+       _NOLIBC_SYSCALL_REG _arg5 __asm__ ("$8") = __nolibc_arg_to_reg(arg5); \
+       _NOLIBC_SYSCALL_REG _arg6 __asm__ ("$9") = __nolibc_arg_to_reg(arg6); \
                                                                              \
        __asm__ volatile (                                                    \
                "syscall\n"                                                   \