[PATCH 3/3] selftests/seccomp: add sparc32 support

From: Ludwig Rydberg

Date: Wed Oct 14 2026 - 04:09:58 EST


Add SPARC32 definitions to seccomp_bpf selftest.

Reuse the sparc64 register handling on sparc32 but adapt the carry
bit handling to use %tstate on sparc64 and %psr on sparc32.

Signed-off-by: Ludwig Rydberg <ludwig.rydberg@xxxxxxxxxxx>
---
tools/testing/selftests/seccomp/seccomp_bpf.c | 38 +++++++++++++------
1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 3711060c22a7..60ae1de8201d 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -1872,10 +1872,21 @@ TEST_F(TRACE_poke, getpid_runs_normally)
# define ARCH_REGS struct user_regs_struct
# define SYSCALL_NUM(_regs) (_regs).orig_d0
# define SYSCALL_RET(_regs) (_regs).d0
-#elif defined(__sparc__) && defined(__arch64__)
+#elif defined(__sparc__)
# include <asm/ptrace.h>
+
+# if defined(__arch64__)
+# include <asm/pstate.h>
+# define CARRY_MASK (TSTATE_ICARRY | TSTATE_XCARRY)
+# define SPARC_CARRY_REG(_regs) ((_regs).tstate)
+# else
+# include <asm/psr.h>
+# define CARRY_MASK PSR_C
+# define SPARC_CARRY_REG(_regs) ((_regs).psr)
+# endif
+
/*
- * PTRACE_GETREGS64/PTRACE_SETREGS64 transfer the uapi struct pt_regs,
+ * PTRACE_GETREGS{64}/PTRACE_SETREGS{64} transfer the uapi struct pt_regs,
* but in the historical layout that omits %g0: the blob starts at %g1,
* so every u_regs index is one lower than the register number suggests.
*/
@@ -1883,20 +1894,20 @@ TEST_F(TRACE_poke, getpid_runs_normally)
# define SYSCALL_NUM(_regs) (_regs).u_regs[0] /* %g1 */
# define SYSCALL_RET(_regs) (_regs).u_regs[7] /* %o0 */
/*
- * A syscall error is signaled by the carry bit in tstate, with the
- * errno held in %o0 as a positive value; the carry can only be
- * written reliably once the syscall has been skipped or has run.
+ * A syscall error is signaled by the carry bit in tstate (SPARC64) or
+ * psr (SPARC32), with the errno held in %o0 as a positive value;
+ * the carry can only be written reliably once the syscall has been
+ * skipped or has run.
*/
-# define SPARC64_TSTATE_CARRY 0x0000001100000000UL /* xcc.c | icc.c */
# define SYSCALL_RET_SET(_regs, _val) \
do { \
typeof(_val) _result = (_val); \
if (_result < 0) { \
SYSCALL_RET(_regs) = -_result; \
- (_regs).tstate |= SPARC64_TSTATE_CARRY; \
+ SPARC_CARRY_REG(_regs) |= CARRY_MASK; \
} else { \
SYSCALL_RET(_regs) = _result; \
- (_regs).tstate &= ~SPARC64_TSTATE_CARRY; \
+ SPARC_CARRY_REG(_regs) &= ~CARRY_MASK; \
} \
} while (0)
# define SYSCALL_RET_SET_ON_PTRACE_EXIT
@@ -1967,14 +1978,19 @@ const bool ptrace_entry_set_syscall_ret =
#if defined(__x86_64__) || defined(__i386__) || defined(__mips__) || defined(__mc68000__)
# define ARCH_GETREGS(_regs) ptrace(PTRACE_GETREGS, tracee, 0, &(_regs))
# define ARCH_SETREGS(_regs) ptrace(PTRACE_SETREGS, tracee, 0, &(_regs))
-#elif defined(__sparc__) && defined(__arch64__)
+#elif defined(__sparc__)
+# if defined(__arch64__)
/*
* The NT_PRSTATUS regset appends the register window, which struct
* pt_regs does not carry; the sparc-specific requests transfer
* struct pt_regs directly (and take the buffer in addr).
*/
-# define ARCH_GETREGS(_regs) ptrace(PTRACE_GETREGS64, tracee, &(_regs), 0)
-# define ARCH_SETREGS(_regs) ptrace(PTRACE_SETREGS64, tracee, &(_regs), 0)
+# define ARCH_GETREGS(_regs) ptrace(PTRACE_GETREGS64, tracee, &(_regs), 0)
+# define ARCH_SETREGS(_regs) ptrace(PTRACE_SETREGS64, tracee, &(_regs), 0)
+# else
+# define ARCH_GETREGS(_regs) ptrace(PTRACE_GETREGS, tracee, &(_regs), 0)
+# define ARCH_SETREGS(_regs) ptrace(PTRACE_SETREGS, tracee, &(_regs), 0)
+# endif
#else
# define ARCH_GETREGS(_regs) ({ \
struct iovec __v; \
--
2.35.3