powerpc/64s/syscall: Use pt_regs.trap to distinguish syscall ABI difference between...
authorNicholas Piggin <npiggin@gmail.com>
Thu, 20 May 2021 11:19:30 +0000 (21:19 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 20 May 2021 14:58:03 +0000 (00:58 +1000)
The sc and scv 0 system calls have different ABI conventions, and
ptracers need to know which system call type is being used if they want
to look at the syscall registers.

Document that pt_regs.trap can be used for this, and fix one in-tree user
to work with scv 0 syscalls.

Fixes: 7fa95f9adaee ("powerpc/64s: system call support for scv/rfscv instructions")
Cc: stable@vger.kernel.org # v5.9+
Reported-by: "Dmitry V. Levin" <ldv@altlinux.org>
Suggested-by: "Dmitry V. Levin" <ldv@altlinux.org>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210520111931.2597127-1-npiggin@gmail.com
Documentation/powerpc/syscall64-abi.rst
tools/testing/selftests/seccomp/seccomp_bpf.c

index dabee37..56490c4 100644 (file)
@@ -109,6 +109,16 @@ auxiliary vector.
 
 scv 0 syscalls will always behave as PPC_FEATURE2_HTM_NOSC.
 
+ptrace
+------
+When ptracing system calls (PTRACE_SYSCALL), the pt_regs.trap value contains
+the system call type that can be used to distinguish between sc and scv 0
+system calls, and the different register conventions can be accounted for.
+
+If the value of (pt_regs.trap & 0xfff0) is 0xc00 then the system call was
+performed with the sc instruction, if it is 0x3000 then the system call was
+performed with the scv 0 instruction.
+
 vsyscall
 ========
 
index 98c3b64..e3d5c77 100644 (file)
@@ -1753,16 +1753,25 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 # define SYSCALL_RET_SET(_regs, _val)                          \
        do {                                                    \
                typeof(_val) _result = (_val);                  \
-               /*                                              \
-                * A syscall error is signaled by CR0 SO bit    \
-                * and the code is stored as a positive value.  \
-                */                                             \
-               if (_result < 0) {                              \
-                       SYSCALL_RET(_regs) = -_result;          \
-                       (_regs).ccr |= 0x10000000;              \
-               } else {                                        \
+               if ((_regs.trap & 0xfff0) == 0x3000) {          \
+                       /*                                      \
+                        * scv 0 system call uses -ve result    \
+                        * for error, so no need to adjust.     \
+                        */                                     \
                        SYSCALL_RET(_regs) = _result;           \
-                       (_regs).ccr &= ~0x10000000;             \
+               } else {                                        \
+                       /*                                      \
+                        * A syscall error is signaled by the   \
+                        * CR0 SO bit and the code is stored as \
+                        * a positive value.                    \
+                        */                                     \
+                       if (_result < 0) {                      \
+                               SYSCALL_RET(_regs) = -_result;  \
+                               (_regs).ccr |= 0x10000000;      \
+                       } else {                                \
+                               SYSCALL_RET(_regs) = _result;   \
+                               (_regs).ccr &= ~0x10000000;     \
+                       }                                       \
                }                                               \
        } while (0)
 # define SYSCALL_RET_SET_ON_PTRACE_EXIT