1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#ifndef _ASM_POWERPC_PTRACE_H
20#define _ASM_POWERPC_PTRACE_H
21
22#include <uapi/asm/ptrace.h>
23#include <asm/asm-const.h>
24
25#ifndef __ASSEMBLY__
26struct pt_regs
27{
28 union {
29 struct user_pt_regs user_regs;
30 struct {
31 unsigned long gpr[32];
32 unsigned long nip;
33 unsigned long msr;
34 unsigned long orig_gpr3;
35 unsigned long ctr;
36 unsigned long link;
37 unsigned long xer;
38 unsigned long ccr;
39#ifdef CONFIG_PPC64
40 unsigned long softe;
41#else
42 unsigned long mq;
43#endif
44 unsigned long trap;
45 unsigned long dar;
46 unsigned long dsisr;
47 unsigned long result;
48 };
49 };
50
51 union {
52 struct {
53#ifdef CONFIG_PPC64
54 unsigned long ppr;
55#endif
56#ifdef CONFIG_PPC_KUAP
57 unsigned long kuap;
58#endif
59 };
60 unsigned long __pad[2];
61 };
62};
63#endif
64
65#ifdef __powerpc64__
66
67
68
69
70
71
72
73
74
75
76#define USER_REDZONE_SIZE 512
77#define KERNEL_REDZONE_SIZE 288
78
79#define STACK_FRAME_OVERHEAD 112
80#define STACK_FRAME_LR_SAVE 2
81#define STACK_FRAME_REGS_MARKER ASM_CONST(0x7265677368657265)
82#define STACK_INT_FRAME_SIZE (sizeof(struct pt_regs) + \
83 STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
84#define STACK_FRAME_MARKER 12
85
86#ifdef PPC64_ELF_ABI_v2
87#define STACK_FRAME_MIN_SIZE 32
88#else
89#define STACK_FRAME_MIN_SIZE STACK_FRAME_OVERHEAD
90#endif
91
92
93#define __SIGNAL_FRAMESIZE 128
94#define __SIGNAL_FRAMESIZE32 64
95
96#else
97
98#define USER_REDZONE_SIZE 0
99#define KERNEL_REDZONE_SIZE 0
100#define STACK_FRAME_OVERHEAD 16
101#define STACK_FRAME_LR_SAVE 1
102#define STACK_FRAME_REGS_MARKER ASM_CONST(0x72656773)
103#define STACK_INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
104#define STACK_FRAME_MARKER 2
105#define STACK_FRAME_MIN_SIZE STACK_FRAME_OVERHEAD
106
107
108#define __SIGNAL_FRAMESIZE 64
109
110#endif
111
112#ifndef __ASSEMBLY__
113
114static inline unsigned long instruction_pointer(struct pt_regs *regs)
115{
116 return regs->nip;
117}
118
119static inline void instruction_pointer_set(struct pt_regs *regs,
120 unsigned long val)
121{
122 regs->nip = val;
123}
124
125static inline unsigned long user_stack_pointer(struct pt_regs *regs)
126{
127 return regs->gpr[1];
128}
129
130static inline unsigned long frame_pointer(struct pt_regs *regs)
131{
132 return 0;
133}
134
135#ifdef CONFIG_SMP
136extern unsigned long profile_pc(struct pt_regs *regs);
137#else
138#define profile_pc(regs) instruction_pointer(regs)
139#endif
140
141long do_syscall_trace_enter(struct pt_regs *regs);
142void do_syscall_trace_leave(struct pt_regs *regs);
143
144#define kernel_stack_pointer(regs) ((regs)->gpr[1])
145static inline int is_syscall_success(struct pt_regs *regs)
146{
147 return !(regs->ccr & 0x10000000);
148}
149
150static inline long regs_return_value(struct pt_regs *regs)
151{
152 if (is_syscall_success(regs))
153 return regs->gpr[3];
154 else
155 return -regs->gpr[3];
156}
157
158static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
159{
160 regs->gpr[3] = rc;
161}
162
163#ifdef __powerpc64__
164#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
165#else
166#define user_mode(regs) (((regs)->msr & MSR_PR) != 0)
167#endif
168
169#define force_successful_syscall_return() \
170 do { \
171 set_thread_flag(TIF_NOERROR); \
172 } while(0)
173
174struct task_struct;
175extern int ptrace_get_reg(struct task_struct *task, int regno,
176 unsigned long *data);
177extern int ptrace_put_reg(struct task_struct *task, int regno,
178 unsigned long data);
179
180#define current_pt_regs() \
181 ((struct pt_regs *)((unsigned long)task_stack_page(current) + THREAD_SIZE) - 1)
182
183#ifdef __powerpc64__
184#ifdef CONFIG_PPC_BOOK3S
185#define TRAP_FLAGS_MASK 0x10
186#define TRAP(regs) ((regs)->trap & ~TRAP_FLAGS_MASK)
187#define FULL_REGS(regs) true
188#define SET_FULL_REGS(regs) do { } while (0)
189#else
190#define TRAP_FLAGS_MASK 0x11
191#define TRAP(regs) ((regs)->trap & ~TRAP_FLAGS_MASK)
192#define FULL_REGS(regs) (((regs)->trap & 1) == 0)
193#define SET_FULL_REGS(regs) ((regs)->trap |= 1)
194#endif
195#define CHECK_FULL_REGS(regs) BUG_ON(!FULL_REGS(regs))
196#define NV_REG_POISON 0xdeadbeefdeadbeefUL
197#else
198
199
200
201
202
203
204
205#define TRAP_FLAGS_MASK 0x1F
206#define TRAP(regs) ((regs)->trap & ~TRAP_FLAGS_MASK)
207#define FULL_REGS(regs) (((regs)->trap & 1) == 0)
208#define SET_FULL_REGS(regs) ((regs)->trap |= 1)
209#define IS_CRITICAL_EXC(regs) (((regs)->trap & 2) != 0)
210#define IS_MCHECK_EXC(regs) (((regs)->trap & 4) != 0)
211#define IS_DEBUG_EXC(regs) (((regs)->trap & 8) != 0)
212#define NV_REG_POISON 0xdeadbeef
213#define CHECK_FULL_REGS(regs) \
214do { \
215 if ((regs)->trap & 1) \
216 printk(KERN_CRIT "%s: partial register set\n", __func__); \
217} while (0)
218#endif
219
220static inline void set_trap(struct pt_regs *regs, unsigned long val)
221{
222 regs->trap = (regs->trap & TRAP_FLAGS_MASK) | (val & ~TRAP_FLAGS_MASK);
223}
224
225static inline bool trap_is_scv(struct pt_regs *regs)
226{
227 return (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && TRAP(regs) == 0x3000);
228}
229
230static inline bool trap_is_syscall(struct pt_regs *regs)
231{
232 return (trap_is_scv(regs) || TRAP(regs) == 0xc00);
233}
234
235static inline bool trap_norestart(struct pt_regs *regs)
236{
237 return regs->trap & 0x10;
238}
239
240static inline void set_trap_norestart(struct pt_regs *regs)
241{
242 regs->trap |= 0x10;
243}
244
245#define arch_has_single_step() (1)
246#define arch_has_block_step() (true)
247#define ARCH_HAS_USER_SINGLE_STEP_REPORT
248
249
250
251
252
253#include <linux/stddef.h>
254#include <linux/thread_info.h>
255extern int regs_query_register_offset(const char *name);
256extern const char *regs_query_register_name(unsigned int offset);
257#define MAX_REG_OFFSET (offsetof(struct pt_regs, dsisr))
258
259
260
261
262
263
264
265
266
267
268static inline unsigned long regs_get_register(struct pt_regs *regs,
269 unsigned int offset)
270{
271 if (unlikely(offset > MAX_REG_OFFSET))
272 return 0;
273 return *(unsigned long *)((unsigned long)regs + offset);
274}
275
276
277
278
279
280
281
282
283
284
285static inline bool regs_within_kernel_stack(struct pt_regs *regs,
286 unsigned long addr)
287{
288 return ((addr & ~(THREAD_SIZE - 1)) ==
289 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
290}
291
292
293
294
295
296
297
298
299
300
301static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
302 unsigned int n)
303{
304 unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
305 addr += n;
306 if (regs_within_kernel_stack(regs, (unsigned long)addr))
307 return *addr;
308 else
309 return 0;
310}
311
312#endif
313
314#ifndef __powerpc64__
315
316#define PT_SOFTE PT_MQ
317#else
318#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1)
319#define PT_VR0_32 164
320#define PT_VSCR_32 (PT_VR0 + 32*4 + 3)
321#define PT_VRSAVE_32 (PT_VR0 + 33*4)
322#define PT_VSR0_32 300
323#endif
324#endif
325