[PATCH] tools/nolibc: MIPS: fix clobbers of 'lo' and 'hi' registers on different ISAs

Thomas Weißschuh posted 1 patch 1 month, 1 week ago
There is a newer version of this series
tools/include/nolibc/arch-mips.h | 33 +++++++++++++++++++++++++++------
1 file changed, 27 insertions(+), 6 deletions(-)
[PATCH] tools/nolibc: MIPS: fix clobbers of 'lo' and 'hi' registers on different ISAs
Posted by Thomas Weißschuh 1 month, 1 week ago
Earlier MIPS64 ISAs still provide the 'lo' and 'hi' special registers.
These are clobbered by system calls and need to be marked as such to
avoid miscompilations.
Also 32-bit ISAs from r6 on do not define the 'lo' and 'hi' registers.

Handle all different combinations of ABI and ISAs.

Fixes: a6a2a8a42972 ("tools/nolibc: MIPS: add support for N64 and N32 ABIs")
Fixes: 66b6f755ad45 ("rcutorture: Import a copy of nolibc")
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
 tools/include/nolibc/arch-mips.h | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
index a72506ceec6b..210bd907b51f 100644
--- a/tools/include/nolibc/arch-mips.h
+++ b/tools/include/nolibc/arch-mips.h
@@ -41,23 +41,44 @@
 
 #if defined(_ABIO32)
 
-#define _NOLIBC_SYSCALL_CLOBBERLIST \
-	"memory", "cc", "at", "v1", "hi", "lo", \
-	"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"
 #define _NOLIBC_SYSCALL_STACK_RESERVE "addiu $sp, $sp, -32\n"
 #define _NOLIBC_SYSCALL_STACK_UNRESERVE "addiu $sp, $sp, 32\n"
 
 #else /* _ABIN32 || _ABI64 */
 
+#define _NOLIBC_SYSCALL_STACK_RESERVE
+#define _NOLIBC_SYSCALL_STACK_UNRESERVE
+
+#endif /* _ABIO32 */
+
+
+#if defined(_ABIO32) && __mips_isa_rev >= 6
+
+#define _NOLIBC_SYSCALL_CLOBBERLIST \
+	"memory", "cc", "at", "v1", \
+	"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"
+
+#elif defined(_ABIO32) && __mips_isa_rev < 6
+
+#define _NOLIBC_SYSCALL_CLOBBERLIST \
+	"memory", "cc", "at", "v1", "hi", "lo", \
+	"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"
+
+#elif __mips_isa_rev >= 6 /* _ABIN32 || _ABI64 */
+
 /* binutils, GCC and clang disagree about register aliases, use numbers instead. */
 #define _NOLIBC_SYSCALL_CLOBBERLIST \
 	"memory", "cc", "at", "v1", \
 	"10", "11", "12", "13", "14", "15", "24", "25"
 
-#define _NOLIBC_SYSCALL_STACK_RESERVE
-#define _NOLIBC_SYSCALL_STACK_UNRESERVE
+#else /* __mips_is_rev < 6 && (_ABIN32 || _ABI64) */
+
+#define _NOLIBC_SYSCALL_CLOBBERLIST \
+	"memory", "cc", "at", "v1", "hi", "lo", \
+	"10", "11", "12", "13", "14", "15", "24", "25"
+
+#endif /* __mips_isa_rev and ABI */
 
-#endif /* _ABIO32 */
 
 #define my_syscall0(num)                                                      \
 ({                                                                            \

---
base-commit: 2961f841b025fb234860bac26dfb7fa7cb0fb122
change-id: 20260218-nolibc-mips-clobber-499e9fbdb5bf

Best regards,
-- 
Thomas Weißschuh <thomas.weissschuh@linutronix.de>

Re: [PATCH] tools/nolibc: MIPS: fix clobbers of 'lo' and 'hi' registers on different ISAs
Posted by Maciej W. Rozycki 2 weeks, 5 days ago
On Wed, 18 Feb 2026, Thomas Weißschuh wrote:

> Earlier MIPS64 ISAs still provide the 'lo' and 'hi' special registers.
> These are clobbered by system calls and need to be marked as such to
> avoid miscompilations.

 Correct.

> Also 32-bit ISAs from r6 on do not define the 'lo' and 'hi' registers.

 There's no MIPS ISA beyond R6 (nanoMIPS is a completely different ISA).  
Also MIPS64r6 is the same in this respect as MIPS32r6 is.

> diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
> index a72506ceec6b..210bd907b51f 100644
> --- a/tools/include/nolibc/arch-mips.h
> +++ b/tools/include/nolibc/arch-mips.h
> @@ -41,23 +41,44 @@
>  
>  #if defined(_ABIO32)
>  
> -#define _NOLIBC_SYSCALL_CLOBBERLIST \
> -	"memory", "cc", "at", "v1", "hi", "lo", \
> -	"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"
>  #define _NOLIBC_SYSCALL_STACK_RESERVE "addiu $sp, $sp, -32\n"
>  #define _NOLIBC_SYSCALL_STACK_UNRESERVE "addiu $sp, $sp, 32\n"
>  
>  #else /* _ABIN32 || _ABI64 */
>  
> +#define _NOLIBC_SYSCALL_STACK_RESERVE
> +#define _NOLIBC_SYSCALL_STACK_UNRESERVE
> +
> +#endif /* _ABIO32 */
> +
> +
> +#if defined(_ABIO32) && __mips_isa_rev >= 6
> +
> +#define _NOLIBC_SYSCALL_CLOBBERLIST \
> +	"memory", "cc", "at", "v1", \
> +	"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"
> +
> +#elif defined(_ABIO32) && __mips_isa_rev < 6
> +
> +#define _NOLIBC_SYSCALL_CLOBBERLIST \
> +	"memory", "cc", "at", "v1", "hi", "lo", \
> +	"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"
> +
> +#elif __mips_isa_rev >= 6 /* _ABIN32 || _ABI64 */
> +
>  /* binutils, GCC and clang disagree about register aliases, use numbers instead. */
>  #define _NOLIBC_SYSCALL_CLOBBERLIST \
>  	"memory", "cc", "at", "v1", \
>  	"10", "11", "12", "13", "14", "15", "24", "25"
>  
> -#define _NOLIBC_SYSCALL_STACK_RESERVE
> -#define _NOLIBC_SYSCALL_STACK_UNRESERVE
> +#else /* __mips_is_rev < 6 && (_ABIN32 || _ABI64) */

 s/__mips_is_rev/__mips_isa_rev/

> +
> +#define _NOLIBC_SYSCALL_CLOBBERLIST \
> +	"memory", "cc", "at", "v1", "hi", "lo", \
> +	"10", "11", "12", "13", "14", "15", "24", "25"
> +
> +#endif /* __mips_isa_rev and ABI */
>  
> -#endif /* _ABIO32 */

 I think this would be more readable/maintainable if you did something 
such as:

#if __mips_isa_rev < 6
#define _NOLIBC_SYSCALL_CLOBBER_HI "hi"
#define _NOLIBC_SYSCALL_CLOBBER_LO "lo"
#else
#define _NOLIBC_SYSCALL_CLOBBER_HI "$0"
#define _NOLIBC_SYSCALL_CLOBBER_LO "$0"
#endif

and then used the macros rather than duplicating the clobber lists.  Or 
you could reuse the approach taken with VDSO_SYSCALL_CLOBBERS, perhaps a 
bit messy, also when it comes to the name of the macro.
Re: [PATCH] tools/nolibc: MIPS: fix clobbers of 'lo' and 'hi' registers on different ISAs
Posted by Thomas Weißschuh 2 weeks, 2 days ago
On Sat, Mar 14, 2026 at 06:01:20PM +0000, Maciej W. Rozycki wrote:
> On Wed, 18 Feb 2026, Thomas Weißschuh wrote:
> 
> > Earlier MIPS64 ISAs still provide the 'lo' and 'hi' special registers.
> > These are clobbered by system calls and need to be marked as such to
> > avoid miscompilations.
> 
>  Correct.
> 
> > Also 32-bit ISAs from r6 on do not define the 'lo' and 'hi' registers.
> 
>  There's no MIPS ISA beyond R6 (nanoMIPS is a completely different ISA).  
> Also MIPS64r6 is the same in this respect as MIPS32r6 is.

I'll reword this.

> > diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
> > index a72506ceec6b..210bd907b51f 100644
> > --- a/tools/include/nolibc/arch-mips.h
> > +++ b/tools/include/nolibc/arch-mips.h
> > @@ -41,23 +41,44 @@

(...)

> #if __mips_isa_rev < 6
> #define _NOLIBC_SYSCALL_CLOBBER_HI "hi"
> #define _NOLIBC_SYSCALL_CLOBBER_LO "lo"
> #else
> #define _NOLIBC_SYSCALL_CLOBBER_HI "$0"
> #define _NOLIBC_SYSCALL_CLOBBER_LO "$0"
> #endif

Ack, will use this.

> and then used the macros rather than duplicating the clobber lists.  Or 
> you could reuse the approach taken with VDSO_SYSCALL_CLOBBERS, perhaps a 
> bit messy, also when it comes to the name of the macro.

Reusing code from the core kernel in nolibc is problematic,
as nolibc is licensed more liberally.


Thomas
Re: [PATCH] tools/nolibc: MIPS: fix clobbers of 'lo' and 'hi' registers on different ISAs
Posted by Willy Tarreau 3 weeks, 4 days ago
On Wed, Feb 18, 2026 at 12:45:48PM +0100, Thomas Weißschuh wrote:
> Earlier MIPS64 ISAs still provide the 'lo' and 'hi' special registers.
> These are clobbered by system calls and need to be marked as such to
> avoid miscompilations.
> Also 32-bit ISAs from r6 on do not define the 'lo' and 'hi' registers.
> 
> Handle all different combinations of ABI and ISAs.
> 
> Fixes: a6a2a8a42972 ("tools/nolibc: MIPS: add support for N64 and N32 ABIs")
> Fixes: 66b6f755ad45 ("rcutorture: Import a copy of nolibc")
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>

I trust that you've contemplated way more doc than me on that topic, so
obviously:

Acked-by: Willy Tarreau <w@1wt.eu>

Thanks,
Willy