public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] tools/nolibc: large file support
@ 2026-04-18 10:19 Thomas Weißschuh
  2026-04-18 10:19 ` [PATCH 1/7] tools/nolibc: also handle _llseek system call Thomas Weißschuh
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Thomas Weißschuh @ 2026-04-18 10:19 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Daniel Palmer, linux-kernel, Thomas Weißschuh

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
Thomas Weißschuh (7):
      tools/nolibc: also handle _llseek system call
      tools/nolibc: add __nolibc_arg_to_reg()
      tools/nolibc: cast pointers returned from system calls through integers
      tools/nolibc: handle 64-bit system call arguments on x32
      tools/nolibc: handle 64-bit system call arguments on MIPS N32
      tools/nolibc: open files with O_LARGEFILE
      selftests/nolibc: test large file support

 tools/include/nolibc/arch-mips.h             | 94 +++++++++++++++-------------
 tools/include/nolibc/arch-x86.h              | 70 ++++++++++-----------
 tools/include/nolibc/crt.h                   |  4 ++
 tools/include/nolibc/fcntl.h                 |  4 ++
 tools/include/nolibc/sys.h                   | 14 +++--
 tools/include/nolibc/sys/mman.h              |  6 +-
 tools/testing/selftests/nolibc/nolibc-test.c | 48 ++++++++++++++
 7 files changed, 153 insertions(+), 87 deletions(-)
---
base-commit: 881f42cc68a6723f1fd6bac00b84b9281cf9bca0
change-id: 20260417-nolibc-largefile-90c85e8443cf

Best regards,
--  
Thomas Weißschuh <linux@weissschuh.net>


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/7] tools/nolibc: also handle _llseek system call
  2026-04-18 10:19 [PATCH 0/7] tools/nolibc: large file support Thomas Weißschuh
@ 2026-04-18 10:19 ` Thomas Weißschuh
  2026-04-18 11:23   ` David Laight
  2026-04-18 10:19 ` [PATCH 2/7] tools/nolibc: add __nolibc_arg_to_reg() Thomas Weißschuh
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Thomas Weißschuh @ 2026-04-18 10:19 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Daniel Palmer, linux-kernel, Thomas Weißschuh

On some architectures the llseek system call contains a leading
underscore. Also check for that one and prefer it over the lseek system
call as it is necessary for 64-bit offset handling.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 tools/include/nolibc/sys.h | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h
index 6335fd51f07f..82a1e36e7290 100644
--- a/tools/include/nolibc/sys.h
+++ b/tools/include/nolibc/sys.h
@@ -597,12 +597,18 @@ int link(const char *old, const char *new)
 static __attribute__((unused))
 off_t _sys_lseek(int fd, off_t offset, int whence)
 {
-#if defined(__NR_llseek)
+#if defined(__NR_llseek) || defined(__NR__llseek)
 	__kernel_loff_t loff = 0;
+	int ret, nr_llseek;
 	off_t result;
-	int ret;
 
-	ret = __nolibc_syscall5(__NR_llseek, fd, offset >> 32, (uint32_t)offset, &loff, whence);
+#if defined(__NR_llseek)
+	nr_llseek = __NR_llseek;
+#else
+	nr_llseek = __NR__llseek;
+#endif
+
+	ret = __nolibc_syscall5(nr_llseek, fd, offset >> 32, (uint32_t)offset, &loff, whence);
 	if (ret < 0)
 		result = ret;
 	else

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/7] tools/nolibc: add __nolibc_arg_to_reg()
  2026-04-18 10:19 [PATCH 0/7] tools/nolibc: large file support Thomas Weißschuh
  2026-04-18 10:19 ` [PATCH 1/7] tools/nolibc: also handle _llseek system call Thomas Weißschuh
@ 2026-04-18 10:19 ` Thomas Weißschuh
  2026-04-18 10:19 ` [PATCH 3/7] tools/nolibc: cast pointers returned from system calls through integers Thomas Weißschuh
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Thomas Weißschuh @ 2026-04-18 10:19 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Daniel Palmer, linux-kernel, Thomas Weißschuh

In the architecture specific system call glue, all arguments are
currently casted to 'long' to fit into registers. This works for
pointers as 'long' has the same size as pointers.
However the system call registers for X32 and MIPS N32 need to be
'long long' to work correctly for 64-bit values expected by the system
call ABI. Casting a pointer to a 'long long' will produce a compiler
warning while casting 64-bit integers to 'long' will truncate those.

Add a helper which can be used to correctly cast both pointers and
integers into 'long long' registers. Cast the pointers through
'unsigned' to avoid any sign extensions.

Both builtins have been available since at least GCC 3 and clang 3.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 tools/include/nolibc/crt.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tools/include/nolibc/crt.h b/tools/include/nolibc/crt.h
index f38590a05adf..2414114b7752 100644
--- a/tools/include/nolibc/crt.h
+++ b/tools/include/nolibc/crt.h
@@ -11,6 +11,10 @@
 
 #include "compiler.h"
 
+#define __nolibc_arg_to_reg(_a)									\
+	__builtin_choose_expr(__builtin_classify_type(_a) == __builtin_classify_type(NULL),	\
+			      (unsigned long)(_a), (_a))
+
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/7] tools/nolibc: cast pointers returned from system calls through integers
  2026-04-18 10:19 [PATCH 0/7] tools/nolibc: large file support Thomas Weißschuh
  2026-04-18 10:19 ` [PATCH 1/7] tools/nolibc: also handle _llseek system call Thomas Weißschuh
  2026-04-18 10:19 ` [PATCH 2/7] tools/nolibc: add __nolibc_arg_to_reg() Thomas Weißschuh
@ 2026-04-18 10:19 ` Thomas Weißschuh
  2026-04-18 10:19 ` [PATCH 4/7] tools/nolibc: handle 64-bit system call arguments on x32 Thomas Weißschuh
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Thomas Weißschuh @ 2026-04-18 10:19 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Daniel Palmer, linux-kernel, Thomas Weißschuh

Currently all system call wrappers return 'long' integers which can be
directly cast to 'void *' if the returned value is actually a pointer.
An upcoming change will change the system call wrappers to sometimes
return 'long long' which can not be cast to a pointer directly.

Add explicit cast through 'long' to prepare for this.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 tools/include/nolibc/sys.h      | 2 +-
 tools/include/nolibc/sys/mman.h | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h
index 82a1e36e7290..e4b6ec02bf95 100644
--- a/tools/include/nolibc/sys.h
+++ b/tools/include/nolibc/sys.h
@@ -87,7 +87,7 @@ static __inline__ int __nolibc_enosys(const char *syscall, ...)
 static __attribute__((unused))
 void *_sys_brk(void *addr)
 {
-	return (void *)__nolibc_syscall1(__NR_brk, addr);
+	return (void *)(unsigned long)__nolibc_syscall1(__NR_brk, addr);
 }
 
 static __attribute__((unused))
diff --git a/tools/include/nolibc/sys/mman.h b/tools/include/nolibc/sys/mman.h
index 91d77a51412d..72bc1d43d1d4 100644
--- a/tools/include/nolibc/sys/mman.h
+++ b/tools/include/nolibc/sys/mman.h
@@ -27,7 +27,7 @@ void *_sys_mmap(void *addr, size_t length, int prot, int flags, int fd,
 	n = __NR_mmap;
 #endif
 
-	return (void *)__nolibc_syscall6(n, addr, length, prot, flags, fd, offset);
+	return (void *)(unsigned long)__nolibc_syscall6(n, addr, length, prot, flags, fd, offset);
 }
 #endif
 
@@ -46,8 +46,8 @@ void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
 static __attribute__((unused))
 void *_sys_mremap(void *old_address, size_t old_size, size_t new_size, int flags, void *new_address)
 {
-	return (void *)__nolibc_syscall5(__NR_mremap, old_address, old_size,
-					 new_size, flags, new_address);
+	return (void *)(unsigned long)__nolibc_syscall5(__NR_mremap, old_address, old_size,
+							new_size, flags, new_address);
 }
 
 static __attribute__((unused))

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/7] tools/nolibc: handle 64-bit system call arguments on x32
  2026-04-18 10:19 [PATCH 0/7] tools/nolibc: large file support Thomas Weißschuh
                   ` (2 preceding siblings ...)
  2026-04-18 10:19 ` [PATCH 3/7] tools/nolibc: cast pointers returned from system calls through integers Thomas Weißschuh
@ 2026-04-18 10:19 ` Thomas Weißschuh
  2026-04-18 10:20 ` [PATCH 5/7] tools/nolibc: handle 64-bit system call arguments on MIPS N32 Thomas Weißschuh
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Thomas Weißschuh @ 2026-04-18 10:19 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Daniel Palmer, linux-kernel, Thomas Weißschuh

The x32 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 x32. As on x86_64 'long' and 'long long' are
the same, this does not change the behavior there.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 tools/include/nolibc/arch-x86.h | 70 ++++++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 35 deletions(-)

diff --git a/tools/include/nolibc/arch-x86.h b/tools/include/nolibc/arch-x86.h
index 769ba01a8629..7a0882c6e942 100644
--- a/tools/include/nolibc/arch-x86.h
+++ b/tools/include/nolibc/arch-x86.h
@@ -202,8 +202,8 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
 
 #define __nolibc_syscall0(num)                                                \
 ({                                                                            \
-	long _ret;                                                            \
-	register long _num  __asm__ ("rax") = (num);                          \
+	long long _ret;                                                       \
+	register long long _num  __asm__ ("rax") = (num);                     \
 									      \
 	__asm__ volatile (                                                    \
 		"syscall\n"                                                   \
@@ -216,9 +216,9 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
 
 #define __nolibc_syscall1(num, arg1)                                          \
 ({                                                                            \
-	long _ret;                                                            \
-	register long _num  __asm__ ("rax") = (num);                          \
-	register long _arg1 __asm__ ("rdi") = (long)(arg1);                   \
+	long long _ret;                                                       \
+	register long long _num  __asm__ ("rax") = (num);                     \
+	register long long _arg1 __asm__ ("rdi") = __nolibc_arg_to_reg(arg1); \
 									      \
 	__asm__ volatile (                                                    \
 		"syscall\n"                                                   \
@@ -232,10 +232,10 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
 
 #define __nolibc_syscall2(num, arg1, arg2)                                    \
 ({                                                                            \
-	long _ret;                                                            \
-	register long _num  __asm__ ("rax") = (num);                          \
-	register long _arg1 __asm__ ("rdi") = (long)(arg1);                   \
-	register long _arg2 __asm__ ("rsi") = (long)(arg2);                   \
+	long long _ret;                                                       \
+	register long long _num  __asm__ ("rax") = (num);                     \
+	register long long _arg1 __asm__ ("rdi") = __nolibc_arg_to_reg(arg1); \
+	register long long _arg2 __asm__ ("rsi") = __nolibc_arg_to_reg(arg2); \
 									      \
 	__asm__ volatile (                                                    \
 		"syscall\n"                                                   \
@@ -249,11 +249,11 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
 
 #define __nolibc_syscall3(num, arg1, arg2, arg3)                              \
 ({                                                                            \
-	long _ret;                                                            \
-	register long _num  __asm__ ("rax") = (num);                          \
-	register long _arg1 __asm__ ("rdi") = (long)(arg1);                   \
-	register long _arg2 __asm__ ("rsi") = (long)(arg2);                   \
-	register long _arg3 __asm__ ("rdx") = (long)(arg3);                   \
+	long long _ret;                                                       \
+	register long long _num  __asm__ ("rax") = (num);                     \
+	register long long _arg1 __asm__ ("rdi") = __nolibc_arg_to_reg(arg1); \
+	register long long _arg2 __asm__ ("rsi") = __nolibc_arg_to_reg(arg2); \
+	register long long _arg3 __asm__ ("rdx") = __nolibc_arg_to_reg(arg3); \
 									      \
 	__asm__ volatile (                                                    \
 		"syscall\n"                                                   \
@@ -267,12 +267,12 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
 
 #define __nolibc_syscall4(num, arg1, arg2, arg3, arg4)                        \
 ({                                                                            \
-	long _ret;                                                            \
-	register long _num  __asm__ ("rax") = (num);                          \
-	register long _arg1 __asm__ ("rdi") = (long)(arg1);                   \
-	register long _arg2 __asm__ ("rsi") = (long)(arg2);                   \
-	register long _arg3 __asm__ ("rdx") = (long)(arg3);                   \
-	register long _arg4 __asm__ ("r10") = (long)(arg4);                   \
+	long long _ret;                                                       \
+	register long long _num  __asm__ ("rax") = (num);                     \
+	register long long _arg1 __asm__ ("rdi") = __nolibc_arg_to_reg(arg1); \
+	register long long _arg2 __asm__ ("rsi") = __nolibc_arg_to_reg(arg2); \
+	register long long _arg3 __asm__ ("rdx") = __nolibc_arg_to_reg(arg3); \
+	register long long _arg4 __asm__ ("r10") = __nolibc_arg_to_reg(arg4); \
 									      \
 	__asm__ volatile (                                                    \
 		"syscall\n"                                                   \
@@ -286,13 +286,13 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
 
 #define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5)                  \
 ({                                                                            \
-	long _ret;                                                            \
-	register long _num  __asm__ ("rax") = (num);                          \
-	register long _arg1 __asm__ ("rdi") = (long)(arg1);                   \
-	register long _arg2 __asm__ ("rsi") = (long)(arg2);                   \
-	register long _arg3 __asm__ ("rdx") = (long)(arg3);                   \
-	register long _arg4 __asm__ ("r10") = (long)(arg4);                   \
-	register long _arg5 __asm__ ("r8")  = (long)(arg5);                   \
+	long long _ret;                                                       \
+	register long long _num  __asm__ ("rax") = (num);                     \
+	register long long _arg1 __asm__ ("rdi") = __nolibc_arg_to_reg(arg1); \
+	register long long _arg2 __asm__ ("rsi") = __nolibc_arg_to_reg(arg2); \
+	register long long _arg3 __asm__ ("rdx") = __nolibc_arg_to_reg(arg3); \
+	register long long _arg4 __asm__ ("r10") = __nolibc_arg_to_reg(arg4); \
+	register long long _arg5 __asm__ ("r8")  = __nolibc_arg_to_reg(arg5); \
 									      \
 	__asm__ volatile (                                                    \
 		"syscall\n"                                                   \
@@ -306,14 +306,14 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
 
 #define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)            \
 ({                                                                            \
-	long _ret;                                                            \
-	register long _num  __asm__ ("rax") = (num);                          \
-	register long _arg1 __asm__ ("rdi") = (long)(arg1);                   \
-	register long _arg2 __asm__ ("rsi") = (long)(arg2);                   \
-	register long _arg3 __asm__ ("rdx") = (long)(arg3);                   \
-	register long _arg4 __asm__ ("r10") = (long)(arg4);                   \
-	register long _arg5 __asm__ ("r8")  = (long)(arg5);                   \
-	register long _arg6 __asm__ ("r9")  = (long)(arg6);                   \
+	long long _ret;                                                       \
+	register long long _num  __asm__ ("rax") = (num);                     \
+	register long long _arg1 __asm__ ("rdi") = __nolibc_arg_to_reg(arg1); \
+	register long long _arg2 __asm__ ("rsi") = __nolibc_arg_to_reg(arg2); \
+	register long long _arg3 __asm__ ("rdx") = __nolibc_arg_to_reg(arg3); \
+	register long long _arg4 __asm__ ("r10") = __nolibc_arg_to_reg(arg4); \
+	register long long _arg5 __asm__ ("r8")  = __nolibc_arg_to_reg(arg5); \
+	register long long _arg6 __asm__ ("r9")  = __nolibc_arg_to_reg(arg6); \
 									      \
 	__asm__ volatile (                                                    \
 		"syscall\n"                                                   \

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/7] tools/nolibc: handle 64-bit system call arguments on MIPS N32
  2026-04-18 10:19 [PATCH 0/7] tools/nolibc: large file support Thomas Weißschuh
                   ` (3 preceding siblings ...)
  2026-04-18 10:19 ` [PATCH 4/7] tools/nolibc: handle 64-bit system call arguments on x32 Thomas Weißschuh
@ 2026-04-18 10:20 ` Thomas Weißschuh
  2026-04-18 11:14   ` David Laight
  2026-04-18 10:20 ` [PATCH 6/7] tools/nolibc: open files with O_LARGEFILE Thomas Weißschuh
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Thomas Weißschuh @ 2026-04-18 10:20 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Daniel Palmer, linux-kernel, Thomas Weißschuh

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>
---
 tools/include/nolibc/arch-mips.h | 94 +++++++++++++++++++++-------------------
 1 file changed, 49 insertions(+), 45 deletions(-)

diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
index bb9d580ea1b1..557ef34d9df8 100644
--- a/tools/include/nolibc/arch-mips.h
+++ b/tools/include/nolibc/arch-mips.h
@@ -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. */
@@ -66,12 +68,14 @@
 #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                                 \
@@ -104,10 +108,10 @@
 
 #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                                 \
@@ -123,11 +127,11 @@
 
 #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                                 \
@@ -143,11 +147,11 @@
 
 #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                                 \
@@ -165,12 +169,12 @@
 
 #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                                 \
@@ -187,13 +191,13 @@
 
 #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                                 \
@@ -214,12 +218,12 @@
 
 #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"                                                   \
@@ -233,13 +237,13 @@
 
 #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"                                                   \

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/7] tools/nolibc: open files with O_LARGEFILE
  2026-04-18 10:19 [PATCH 0/7] tools/nolibc: large file support Thomas Weißschuh
                   ` (4 preceding siblings ...)
  2026-04-18 10:20 ` [PATCH 5/7] tools/nolibc: handle 64-bit system call arguments on MIPS N32 Thomas Weißschuh
@ 2026-04-18 10:20 ` Thomas Weißschuh
  2026-04-18 10:20 ` [PATCH 7/7] selftests/nolibc: test large file support Thomas Weißschuh
  2026-04-18 14:01 ` [PATCH 0/7] tools/nolibc: " Daniel Palmer
  7 siblings, 0 replies; 15+ messages in thread
From: Thomas Weißschuh @ 2026-04-18 10:20 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Daniel Palmer, linux-kernel, Thomas Weißschuh

nolibc can natively handle large files. Tell this to the kernel by
always using O_LARGEFILE when opening files. This is also how other
libcs do it.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 tools/include/nolibc/fcntl.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tools/include/nolibc/fcntl.h b/tools/include/nolibc/fcntl.h
index ed2f5553c65a..235f7c92fba2 100644
--- a/tools/include/nolibc/fcntl.h
+++ b/tools/include/nolibc/fcntl.h
@@ -29,6 +29,8 @@ int openat(int dirfd, const char *path, int flags, ...)
 {
 	mode_t mode = 0;
 
+	flags |= O_LARGEFILE;
+
 	if (flags & O_CREAT) {
 		va_list args;
 
@@ -55,6 +57,8 @@ int open(const char *path, int flags, ...)
 {
 	mode_t mode = 0;
 
+	flags |= O_LARGEFILE;
+
 	if (flags & O_CREAT) {
 		va_list args;
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/7] selftests/nolibc: test large file support
  2026-04-18 10:19 [PATCH 0/7] tools/nolibc: large file support Thomas Weißschuh
                   ` (5 preceding siblings ...)
  2026-04-18 10:20 ` [PATCH 6/7] tools/nolibc: open files with O_LARGEFILE Thomas Weißschuh
@ 2026-04-18 10:20 ` Thomas Weißschuh
  2026-04-18 14:01 ` [PATCH 0/7] tools/nolibc: " Daniel Palmer
  7 siblings, 0 replies; 15+ messages in thread
From: Thomas Weißschuh @ 2026-04-18 10:20 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Daniel Palmer, linux-kernel, Thomas Weißschuh

Make sure nolibc correctly handles large files.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 tools/testing/selftests/nolibc/nolibc-test.c | 48 ++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
index d3c4facb54c0..1290663df47f 100644
--- a/tools/testing/selftests/nolibc/nolibc-test.c
+++ b/tools/testing/selftests/nolibc/nolibc-test.c
@@ -2,6 +2,7 @@
 
 #define _GNU_SOURCE
 #define _LARGEFILE64_SOURCE
+#define _FILE_OFFSET_BITS 64
 
 /* libc-specific include files
  * The program may be built in 3 ways:
@@ -1364,6 +1365,52 @@ int test_namespace(void)
 	return ret;
 }
 
+int test_large_file(void)
+{
+	off_t large_seek = ((off_t)UINT32_MAX) + 100;
+	int fd, ret, saved_errno;
+	ssize_t written;
+	off_t off;
+
+#if defined(__mips__) && defined(_ABIN32)
+	/* https://lore.kernel.org/qemu-devel/fed03914-a95a-4522-a432-f129264cb2ac@t-8ch.de/ */
+	if (getpid() != 1)
+		return 0;
+#endif
+
+	if (large_seek < UINT32_MAX) {
+		errno = EOVERFLOW;
+		return -1;
+	}
+
+	fd = open("/tmp", O_TMPFILE | O_RDWR, 0644);
+	if (fd == -1)
+		return -1;
+
+	off = lseek(fd, large_seek, SEEK_CUR);
+	if (off == -1) {
+		ret = off;
+		goto out;
+	} else if (off != large_seek) {
+		errno = ERANGE;
+		ret = -1;
+		goto out;
+	}
+
+	written = write(fd, "1", 1);
+	if (written == -1) {
+		ret = written;
+		goto out;
+	}
+
+	ret = 0;
+out:
+	saved_errno = errno;
+	close(fd);
+	errno = saved_errno;
+	return ret;
+}
+
 /* Run syscall tests between IDs <min> and <max>.
  * Return 0 on success, non-zero on failure.
  */
@@ -1508,6 +1555,7 @@ int run_syscall(int min, int max)
 		CASE_TEST(_syscall_noargs);   EXPECT_SYSEQ(is_nolibc, _syscall(__NR_getpid), getpid()); break;
 		CASE_TEST(_syscall_args);     EXPECT_SYSEQ(is_nolibc, _syscall(__NR_statx, 0, NULL, 0, 0, NULL), -EFAULT); break;
 		CASE_TEST(namespace);         EXPECT_SYSZR(euid0 && proc, test_namespace()); break;
+		CASE_TEST(largefile);         EXPECT_SYSZR(1, test_large_file()); break;
 		case __LINE__:
 			return ret; /* must be last */
 		/* note: do not set any defaults so as to permit holes above */

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] tools/nolibc: handle 64-bit system call arguments on MIPS N32
  2026-04-18 10:20 ` [PATCH 5/7] tools/nolibc: handle 64-bit system call arguments on MIPS N32 Thomas Weißschuh
@ 2026-04-18 11:14   ` David Laight
  2026-04-18 11:54     ` Thomas Weißschuh
  0 siblings, 1 reply; 15+ messages in thread
From: David Laight @ 2026-04-18 11:14 UTC (permalink / raw)
  To: Thomas Weißschuh; +Cc: Willy Tarreau, Daniel Palmer, linux-kernel

On Sat, 18 Apr 2026 12:20:00 +0200
Thomas Weißschuh <linux@weissschuh.net> wrote:

> 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>
> ---
>  tools/include/nolibc/arch-mips.h | 94 +++++++++++++++++++++-------------------
>  1 file changed, 49 insertions(+), 45 deletions(-)
> 
> diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
> index bb9d580ea1b1..557ef34d9df8 100644
> --- a/tools/include/nolibc/arch-mips.h
> +++ b/tools/include/nolibc/arch-mips.h
> @@ -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. */
> @@ -66,12 +68,14 @@
>  #define _NOLIBC_SYSCALL_STACK_RESERVE
>  #define _NOLIBC_SYSCALL_STACK_UNRESERVE
>  
> +#define _NOLIBC_SYSCALL_REG register long long
> +
>  #endif /* _ABIO32 */

Since you need to use a #define, did you think about:
#define _NOLIBC_SYSCALL_REG(var, reg) register long long var __asm__ (reg)
to shorten the lines and the repetitive pattern.

>  
>  #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");                             \

	__NOLIBC_SYSCALL_REG(_num, "v0") = (num);
	__NOLIBC_SYSCALL_REG(_arg4, "a3");

...

	David

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/7] tools/nolibc: also handle _llseek system call
  2026-04-18 10:19 ` [PATCH 1/7] tools/nolibc: also handle _llseek system call Thomas Weißschuh
@ 2026-04-18 11:23   ` David Laight
  2026-04-18 11:56     ` Thomas Weißschuh
  0 siblings, 1 reply; 15+ messages in thread
From: David Laight @ 2026-04-18 11:23 UTC (permalink / raw)
  To: Thomas Weißschuh; +Cc: Willy Tarreau, Daniel Palmer, linux-kernel

On Sat, 18 Apr 2026 12:19:56 +0200
Thomas Weißschuh <linux@weissschuh.net> wrote:

> On some architectures the llseek system call contains a leading
> underscore. Also check for that one and prefer it over the lseek system
> call as it is necessary for 64-bit offset handling.
> 
...
> +#if defined(__NR_llseek)
> +	nr_llseek = __NR_llseek;
> +#else
> +	nr_llseek = __NR__llseek;
> +#endif

Is that test the right way around?
The commit messages says prefer _llseek, but that seems to prefer llseek.

	David

> +
> +	ret = __nolibc_syscall5(nr_llseek, fd, offset >> 32, (uint32_t)offset, &loff, whence);
>  	if (ret < 0)
>  		result = ret;
>  	else
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] tools/nolibc: handle 64-bit system call arguments on MIPS N32
  2026-04-18 11:14   ` David Laight
@ 2026-04-18 11:54     ` Thomas Weißschuh
  2026-04-18 16:32       ` David Laight
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Weißschuh @ 2026-04-18 11:54 UTC (permalink / raw)
  To: David Laight; +Cc: Willy Tarreau, Daniel Palmer, linux-kernel

Hey David,

Apr 18, 2026 13:14:46 David Laight <david.laight.linux@gmail.com>:

> On Sat, 18 Apr 2026 12:20:00 +0200
> Thomas Weißschuh <linux@weissschuh.net> wrote:
>
>> 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>
>> ---
>> tools/include/nolibc/arch-mips.h | 94 +++++++++++++++++++++-------------------
>> 1 file changed, 49 insertions(+), 45 deletions(-)
>>
>> diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
>> index bb9d580ea1b1..557ef34d9df8 100644
>> --- a/tools/include/nolibc/arch-mips.h
>> +++ b/tools/include/nolibc/arch-mips.h
>> @@ -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. */
>> @@ -66,12 +68,14 @@
>> #define _NOLIBC_SYSCALL_STACK_RESERVE
>> #define _NOLIBC_SYSCALL_STACK_UNRESERVE
>>
>> +#define _NOLIBC_SYSCALL_REG register long long
>> +
>> #endif /* _ABIO32 */
>
> Since you need to use a #define, did you think about:
> #define _NOLIBC_SYSCALL_REG(var, reg) register long long var __asm__ (reg)
> to shorten the lines and the repetitive pattern.

I didn't think of this.
Personally I am fine with both variants.
The parameterized macro is a bit weird
is it breaks the normal syntax.
Let's wait what Willy thinks.

>> #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");                             \
>
>     __NOLIBC_SYSCALL_REG(_num, "v0") = (num);
>     __NOLIBC_SYSCALL_REG(_arg4, "a3");
>
> ...
>
>     David


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/7] tools/nolibc: also handle _llseek system call
  2026-04-18 11:23   ` David Laight
@ 2026-04-18 11:56     ` Thomas Weißschuh
  2026-04-18 16:03       ` David Laight
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Weißschuh @ 2026-04-18 11:56 UTC (permalink / raw)
  To: David Laight; +Cc: Willy Tarreau, Daniel Palmer, linux-kernel

Apr 18, 2026 13:23:43 David Laight <david.laight.linux@gmail.com>:

> On Sat, 18 Apr 2026 12:19:56 +0200
> Thomas Weißschuh <linux@weissschuh.net> wrote:
>
>> On some architectures the llseek system call contains a leading
>> underscore. Also check for that one and prefer it over the lseek system
>> call as it is necessary for 64-bit offset handling.
>>
> ...
>> +#if defined(__NR_llseek)
>> +   nr_llseek = __NR_llseek;
>> +#else
>> +   nr_llseek = __NR__llseek;
>> +#endif
>
> Is that test the right way around?
> The commit messages says prefer _llseek, but that seems to prefer llseek.

Yes. lseek is the ifdef case below.
Here we have _llseek and llseek.
lseek always exists, but may no handle 64 bit offsets.
Only one of llseek and _llseek exists
for one given architecture.

>> +
>> +   ret = __nolibc_syscall5(nr_llseek, fd, offset >> 32, (uint32_t)offset, &loff, whence);
>>     if (ret < 0)
>>         result = ret;
>>     else
>>


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] tools/nolibc: large file support
  2026-04-18 10:19 [PATCH 0/7] tools/nolibc: large file support Thomas Weißschuh
                   ` (6 preceding siblings ...)
  2026-04-18 10:20 ` [PATCH 7/7] selftests/nolibc: test large file support Thomas Weißschuh
@ 2026-04-18 14:01 ` Daniel Palmer
  7 siblings, 0 replies; 15+ messages in thread
From: Daniel Palmer @ 2026-04-18 14:01 UTC (permalink / raw)
  To: Thomas Weißschuh; +Cc: Willy Tarreau, linux-kernel

Hi Thomas,

On Sat, 18 Apr 2026 at 19:20, Thomas Weißschuh <linux@weissschuh.net> wrote:
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> Thomas Weißschuh (7):
>       tools/nolibc: also handle _llseek system call
>       tools/nolibc: add __nolibc_arg_to_reg()
>       tools/nolibc: cast pointers returned from system calls through integers
>       tools/nolibc: handle 64-bit system call arguments on x32
>       tools/nolibc: handle 64-bit system call arguments on MIPS N32
>       tools/nolibc: open files with O_LARGEFILE
>       selftests/nolibc: test large file support

I just wanted fallocate() but it feels like I opened pandora's box. :)
I looked through everything but I don't think I can review really as
I'm just a tinkerer.
The patch for x32 does fix passing through the top 32 bits of the
arguments for fallocate() (Which I was sure was working for some
reason).

Thank you for the hard work!

Cheers,

Daniel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/7] tools/nolibc: also handle _llseek system call
  2026-04-18 11:56     ` Thomas Weißschuh
@ 2026-04-18 16:03       ` David Laight
  0 siblings, 0 replies; 15+ messages in thread
From: David Laight @ 2026-04-18 16:03 UTC (permalink / raw)
  To: Thomas Weißschuh; +Cc: Willy Tarreau, Daniel Palmer, linux-kernel

On Sat, 18 Apr 2026 13:56:46 +0200
Thomas Weißschuh <linux@weissschuh.net> wrote:

> Apr 18, 2026 13:23:43 David Laight <david.laight.linux@gmail.com>:
> 
> > On Sat, 18 Apr 2026 12:19:56 +0200
> > Thomas Weißschuh <linux@weissschuh.net> wrote:
> >  
> >> On some architectures the llseek system call contains a leading
> >> underscore. Also check for that one and prefer it over the lseek system
> >> call as it is necessary for 64-bit offset handling.
> >>  
> > ...  
> >> +#if defined(__NR_llseek)
> >> +   nr_llseek = __NR_llseek;
> >> +#else
> >> +   nr_llseek = __NR__llseek;
> >> +#endif  
> >
> > Is that test the right way around?
> > The commit messages says prefer _llseek, but that seems to prefer llseek.  
> 
> Yes. lseek is the ifdef case below.
> Here we have _llseek and llseek.
> lseek always exists, but may no handle 64 bit offsets.
> Only one of llseek and _llseek exists
> for one given architecture.

Ok, the fact that you said 'prefer' made me think that both might
sometimes exist.

	David

> 
> >> +
> >> +   ret = __nolibc_syscall5(nr_llseek, fd, offset >> 32, (uint32_t)offset, &loff, whence);
> >>     if (ret < 0)
> >>         result = ret;
> >>     else
> >>  
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/7] tools/nolibc: handle 64-bit system call arguments on MIPS N32
  2026-04-18 11:54     ` Thomas Weißschuh
@ 2026-04-18 16:32       ` David Laight
  0 siblings, 0 replies; 15+ messages in thread
From: David Laight @ 2026-04-18 16:32 UTC (permalink / raw)
  To: Thomas Weißschuh; +Cc: Willy Tarreau, Daniel Palmer, linux-kernel

On Sat, 18 Apr 2026 13:54:55 +0200
Thomas Weißschuh <linux@weissschuh.net> wrote:

> Hey David,
> 
> Apr 18, 2026 13:14:46 David Laight <david.laight.linux@gmail.com>:
> 
> > On Sat, 18 Apr 2026 12:20:00 +0200
> > Thomas Weißschuh <linux@weissschuh.net> wrote:
> >  
> >> 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>
> >> ---
> >> tools/include/nolibc/arch-mips.h | 94 +++++++++++++++++++++-------------------
> >> 1 file changed, 49 insertions(+), 45 deletions(-)
> >>
> >> diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
> >> index bb9d580ea1b1..557ef34d9df8 100644
> >> --- a/tools/include/nolibc/arch-mips.h
> >> +++ b/tools/include/nolibc/arch-mips.h
> >> @@ -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. */
> >> @@ -66,12 +68,14 @@
> >> #define _NOLIBC_SYSCALL_STACK_RESERVE
> >> #define _NOLIBC_SYSCALL_STACK_UNRESERVE
> >>
> >> +#define _NOLIBC_SYSCALL_REG register long long
> >> +
> >> #endif /* _ABIO32 */  
> >
> > Since you need to use a #define, did you think about:
> > #define _NOLIBC_SYSCALL_REG(var, reg) register long long var __asm__ (reg)
> > to shorten the lines and the repetitive pattern.  
> 
> I didn't think of this.
> Personally I am fine with both variants.
> The parameterized macro is a bit weird
> is it breaks the normal syntax.
> Let's wait what Willy thinks.

Actually you could take it one stage further:
#define _NOLIBC_SYSCALL_REG(reg) register long long _##reg __asm__ (#reg)
So you'd have:
	_NOLIBC_SYSCALL_REG(a0) = (cast)(arg1);
I'd then use "+r" (_v0), "+r" (_a3).

For the variables that get pushed use the [name] syntax to avoid counting,
they also don't need (well shouldn't need) a local variable - the cast
can be included on the asm line. Giving:
	"sw %[arg5], 16($sp)\n"
	...
	[arg5]"r"((long)(arg5), ...
(Does look like those are all 32bit only, so the (long) cast is correct.)

	David

> 
> >> #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");                             \  
> >
> >     __NOLIBC_SYSCALL_REG(_num, "v0") = (num);
> >     __NOLIBC_SYSCALL_REG(_arg4, "a3");
> >
> > ...
> >
> >     David  
> 
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2026-04-18 16:32 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-18 10:19 [PATCH 0/7] tools/nolibc: large file support Thomas Weißschuh
2026-04-18 10:19 ` [PATCH 1/7] tools/nolibc: also handle _llseek system call Thomas Weißschuh
2026-04-18 11:23   ` David Laight
2026-04-18 11:56     ` Thomas Weißschuh
2026-04-18 16:03       ` David Laight
2026-04-18 10:19 ` [PATCH 2/7] tools/nolibc: add __nolibc_arg_to_reg() Thomas Weißschuh
2026-04-18 10:19 ` [PATCH 3/7] tools/nolibc: cast pointers returned from system calls through integers Thomas Weißschuh
2026-04-18 10:19 ` [PATCH 4/7] tools/nolibc: handle 64-bit system call arguments on x32 Thomas Weißschuh
2026-04-18 10:20 ` [PATCH 5/7] tools/nolibc: handle 64-bit system call arguments on MIPS N32 Thomas Weißschuh
2026-04-18 11:14   ` David Laight
2026-04-18 11:54     ` Thomas Weißschuh
2026-04-18 16:32       ` David Laight
2026-04-18 10:20 ` [PATCH 6/7] tools/nolibc: open files with O_LARGEFILE Thomas Weißschuh
2026-04-18 10:20 ` [PATCH 7/7] selftests/nolibc: test large file support Thomas Weißschuh
2026-04-18 14:01 ` [PATCH 0/7] tools/nolibc: " Daniel Palmer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox