Skip to content

Commit 28ceac6

Browse files
committed
Merge tag 'powerpc-5.13-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: - Fix breakage of strace (and other ptracers etc.) when using the new scv ABI (Power9 or later with glibc >= 2.33). - Fix early_ioremap() on 64-bit, which broke booting on some machines. Thanks to Dmitry V. Levin, Nicholas Piggin, Alexey Kardashevskiy, and Christophe Leroy. * tag 'powerpc-5.13-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/64s/syscall: Fix ptrace syscall info with scv syscalls powerpc/64s/syscall: Use pt_regs.trap to distinguish syscall ABI difference between sc and scv syscalls powerpc: Fix early setup to make early_ioremap() work
2 parents 4d76203 + d72500f commit 28ceac6

File tree

5 files changed

+82
-46
lines changed

5 files changed

+82
-46
lines changed

Documentation/powerpc/syscall64-abi.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,16 @@ auxiliary vector.
109109

110110
scv 0 syscalls will always behave as PPC_FEATURE2_HTM_NOSC.
111111

112+
ptrace
113+
------
114+
When ptracing system calls (PTRACE_SYSCALL), the pt_regs.trap value contains
115+
the system call type that can be used to distinguish between sc and scv 0
116+
system calls, and the different register conventions can be accounted for.
117+
118+
If the value of (pt_regs.trap & 0xfff0) is 0xc00 then the system call was
119+
performed with the sc instruction, if it is 0x3000 then the system call was
120+
performed with the scv 0 instruction.
121+
112122
vsyscall
113123
========
114124

arch/powerpc/include/asm/ptrace.h

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifndef _ASM_POWERPC_PTRACE_H
2020
#define _ASM_POWERPC_PTRACE_H
2121

22+
#include <linux/err.h>
2223
#include <uapi/asm/ptrace.h>
2324
#include <asm/asm-const.h>
2425

@@ -152,25 +153,6 @@ extern unsigned long profile_pc(struct pt_regs *regs);
152153
long do_syscall_trace_enter(struct pt_regs *regs);
153154
void do_syscall_trace_leave(struct pt_regs *regs);
154155

155-
#define kernel_stack_pointer(regs) ((regs)->gpr[1])
156-
static inline int is_syscall_success(struct pt_regs *regs)
157-
{
158-
return !(regs->ccr & 0x10000000);
159-
}
160-
161-
static inline long regs_return_value(struct pt_regs *regs)
162-
{
163-
if (is_syscall_success(regs))
164-
return regs->gpr[3];
165-
else
166-
return -regs->gpr[3];
167-
}
168-
169-
static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
170-
{
171-
regs->gpr[3] = rc;
172-
}
173-
174156
#ifdef __powerpc64__
175157
#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
176158
#else
@@ -235,6 +217,31 @@ static __always_inline void set_trap_norestart(struct pt_regs *regs)
235217
regs->trap |= 0x1;
236218
}
237219

220+
#define kernel_stack_pointer(regs) ((regs)->gpr[1])
221+
static inline int is_syscall_success(struct pt_regs *regs)
222+
{
223+
if (trap_is_scv(regs))
224+
return !IS_ERR_VALUE((unsigned long)regs->gpr[3]);
225+
else
226+
return !(regs->ccr & 0x10000000);
227+
}
228+
229+
static inline long regs_return_value(struct pt_regs *regs)
230+
{
231+
if (trap_is_scv(regs))
232+
return regs->gpr[3];
233+
234+
if (is_syscall_success(regs))
235+
return regs->gpr[3];
236+
else
237+
return -regs->gpr[3];
238+
}
239+
240+
static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
241+
{
242+
regs->gpr[3] = rc;
243+
}
244+
238245
#define arch_has_single_step() (1)
239246
#define arch_has_block_step() (true)
240247
#define ARCH_HAS_USER_SINGLE_STEP_REPORT

arch/powerpc/include/asm/syscall.h

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,17 @@ static inline void syscall_rollback(struct task_struct *task,
4141
static inline long syscall_get_error(struct task_struct *task,
4242
struct pt_regs *regs)
4343
{
44-
/*
45-
* If the system call failed,
46-
* regs->gpr[3] contains a positive ERRORCODE.
47-
*/
48-
return (regs->ccr & 0x10000000UL) ? -regs->gpr[3] : 0;
44+
if (trap_is_scv(regs)) {
45+
unsigned long error = regs->gpr[3];
46+
47+
return IS_ERR_VALUE(error) ? error : 0;
48+
} else {
49+
/*
50+
* If the system call failed,
51+
* regs->gpr[3] contains a positive ERRORCODE.
52+
*/
53+
return (regs->ccr & 0x10000000UL) ? -regs->gpr[3] : 0;
54+
}
4955
}
5056

5157
static inline long syscall_get_return_value(struct task_struct *task,
@@ -58,18 +64,22 @@ static inline void syscall_set_return_value(struct task_struct *task,
5864
struct pt_regs *regs,
5965
int error, long val)
6066
{
61-
/*
62-
* In the general case it's not obvious that we must deal with CCR
63-
* here, as the syscall exit path will also do that for us. However
64-
* there are some places, eg. the signal code, which check ccr to
65-
* decide if the value in r3 is actually an error.
66-
*/
67-
if (error) {
68-
regs->ccr |= 0x10000000L;
69-
regs->gpr[3] = error;
67+
if (trap_is_scv(regs)) {
68+
regs->gpr[3] = (long) error ?: val;
7069
} else {
71-
regs->ccr &= ~0x10000000L;
72-
regs->gpr[3] = val;
70+
/*
71+
* In the general case it's not obvious that we must deal with
72+
* CCR here, as the syscall exit path will also do that for us.
73+
* However there are some places, eg. the signal code, which
74+
* check ccr to decide if the value in r3 is actually an error.
75+
*/
76+
if (error) {
77+
regs->ccr |= 0x10000000L;
78+
regs->gpr[3] = error;
79+
} else {
80+
regs->ccr &= ~0x10000000L;
81+
regs->gpr[3] = val;
82+
}
7383
}
7484
}
7585

arch/powerpc/kernel/setup_64.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,11 @@ void __init early_setup(unsigned long dt_ptr)
369369
apply_feature_fixups();
370370
setup_feature_keys();
371371

372-
early_ioremap_setup();
373-
374372
/* Initialize the hash table or TLB handling */
375373
early_init_mmu();
376374

375+
early_ioremap_setup();
376+
377377
/*
378378
* After firmware and early platform setup code has set things up,
379379
* we note the SPR values for configurable control/performance

tools/testing/selftests/seccomp/seccomp_bpf.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,16 +1753,25 @@ TEST_F(TRACE_poke, getpid_runs_normally)
17531753
# define SYSCALL_RET_SET(_regs, _val) \
17541754
do { \
17551755
typeof(_val) _result = (_val); \
1756-
/* \
1757-
* A syscall error is signaled by CR0 SO bit \
1758-
* and the code is stored as a positive value. \
1759-
*/ \
1760-
if (_result < 0) { \
1761-
SYSCALL_RET(_regs) = -_result; \
1762-
(_regs).ccr |= 0x10000000; \
1763-
} else { \
1756+
if ((_regs.trap & 0xfff0) == 0x3000) { \
1757+
/* \
1758+
* scv 0 system call uses -ve result \
1759+
* for error, so no need to adjust. \
1760+
*/ \
17641761
SYSCALL_RET(_regs) = _result; \
1765-
(_regs).ccr &= ~0x10000000; \
1762+
} else { \
1763+
/* \
1764+
* A syscall error is signaled by the \
1765+
* CR0 SO bit and the code is stored as \
1766+
* a positive value. \
1767+
*/ \
1768+
if (_result < 0) { \
1769+
SYSCALL_RET(_regs) = -_result; \
1770+
(_regs).ccr |= 0x10000000; \
1771+
} else { \
1772+
SYSCALL_RET(_regs) = _result; \
1773+
(_regs).ccr &= ~0x10000000; \
1774+
} \
17661775
} \
17671776
} while (0)
17681777
# define SYSCALL_RET_SET_ON_PTRACE_EXIT

0 commit comments

Comments
 (0)