1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * PowerPC version
4 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
5 *
6 * Derived from "arch/m68k/kernel/ptrace.c"
7 * Copyright (C) 1994 by Hamish Macdonald
8 * Taken from linux/kernel/ptrace.c and modified for M680x0.
9 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
10 *
11 * Modified by Cort Dougan (cort@hq.fsmlabs.com)
12 * and Paul Mackerras (paulus@samba.org).
13 */
14
15 #include <linux/regset.h>
16 #include <linux/ptrace.h>
17 #include <linux/audit.h>
18 #include <linux/context_tracking.h>
19 #include <linux/syscalls.h>
20
21 #include <asm/switch_to.h>
22 #include <asm/debug.h>
23
24 #include "ptrace-decl.h"
25
26 /*
27 * Called by kernel/ptrace.c when detaching..
28 *
29 * Make sure single step bits etc are not set.
30 */
ptrace_disable(struct task_struct * child)31 void ptrace_disable(struct task_struct *child)
32 {
33 /* make sure the single step bit is not set. */
34 user_disable_single_step(child);
35 }
36
arch_ptrace(struct task_struct * child,long request,unsigned long addr,unsigned long data)37 long arch_ptrace(struct task_struct *child, long request,
38 unsigned long addr, unsigned long data)
39 {
40 int ret = -EPERM;
41 void __user *datavp = (void __user *) data;
42 unsigned long __user *datalp = datavp;
43
44 switch (request) {
45 /* read the word at location addr in the USER area. */
46 case PTRACE_PEEKUSR: {
47 unsigned long index, tmp;
48
49 ret = -EIO;
50 /* convert to index and check */
51 index = addr / sizeof(long);
52 if ((addr & (sizeof(long) - 1)) || !child->thread.regs)
53 break;
54
55 if (index < PT_FPR0)
56 ret = ptrace_get_reg(child, (int) index, &tmp);
57 else
58 ret = ptrace_get_fpr(child, index, &tmp);
59
60 if (ret)
61 break;
62 ret = put_user(tmp, datalp);
63 break;
64 }
65
66 /* write the word at location addr in the USER area */
67 case PTRACE_POKEUSR: {
68 unsigned long index;
69
70 ret = -EIO;
71 /* convert to index and check */
72 index = addr / sizeof(long);
73 if ((addr & (sizeof(long) - 1)) || !child->thread.regs)
74 break;
75
76 if (index < PT_FPR0)
77 ret = ptrace_put_reg(child, index, data);
78 else
79 ret = ptrace_put_fpr(child, index, data);
80 break;
81 }
82
83 case PPC_PTRACE_GETHWDBGINFO: {
84 struct ppc_debug_info dbginfo;
85
86 ppc_gethwdinfo(&dbginfo);
87
88 if (copy_to_user(datavp, &dbginfo,
89 sizeof(struct ppc_debug_info)))
90 return -EFAULT;
91 return 0;
92 }
93
94 case PPC_PTRACE_SETHWDEBUG: {
95 struct ppc_hw_breakpoint bp_info;
96
97 if (copy_from_user(&bp_info, datavp,
98 sizeof(struct ppc_hw_breakpoint)))
99 return -EFAULT;
100 return ppc_set_hwdebug(child, &bp_info);
101 }
102
103 case PPC_PTRACE_DELHWDEBUG: {
104 ret = ppc_del_hwdebug(child, data);
105 break;
106 }
107
108 case PTRACE_GET_DEBUGREG:
109 ret = ptrace_get_debugreg(child, addr, datalp);
110 break;
111
112 case PTRACE_SET_DEBUGREG:
113 ret = ptrace_set_debugreg(child, addr, data);
114 break;
115
116 #ifdef CONFIG_PPC64
117 case PTRACE_GETREGS64:
118 #endif
119 case PTRACE_GETREGS: /* Get all pt_regs from the child. */
120 return copy_regset_to_user(child, &user_ppc_native_view,
121 REGSET_GPR,
122 0, sizeof(struct user_pt_regs),
123 datavp);
124
125 #ifdef CONFIG_PPC64
126 case PTRACE_SETREGS64:
127 #endif
128 case PTRACE_SETREGS: /* Set all gp regs in the child. */
129 return copy_regset_from_user(child, &user_ppc_native_view,
130 REGSET_GPR,
131 0, sizeof(struct user_pt_regs),
132 datavp);
133
134 case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */
135 return copy_regset_to_user(child, &user_ppc_native_view,
136 REGSET_FPR,
137 0, sizeof(elf_fpregset_t),
138 datavp);
139
140 case PTRACE_SETFPREGS: /* Set the child FPU state (FPR0...31 + FPSCR) */
141 return copy_regset_from_user(child, &user_ppc_native_view,
142 REGSET_FPR,
143 0, sizeof(elf_fpregset_t),
144 datavp);
145
146 #ifdef CONFIG_ALTIVEC
147 case PTRACE_GETVRREGS:
148 return copy_regset_to_user(child, &user_ppc_native_view,
149 REGSET_VMX,
150 0, (33 * sizeof(vector128) +
151 sizeof(u32)),
152 datavp);
153
154 case PTRACE_SETVRREGS:
155 return copy_regset_from_user(child, &user_ppc_native_view,
156 REGSET_VMX,
157 0, (33 * sizeof(vector128) +
158 sizeof(u32)),
159 datavp);
160 #endif
161 #ifdef CONFIG_VSX
162 case PTRACE_GETVSRREGS:
163 return copy_regset_to_user(child, &user_ppc_native_view,
164 REGSET_VSX,
165 0, 32 * sizeof(double),
166 datavp);
167
168 case PTRACE_SETVSRREGS:
169 return copy_regset_from_user(child, &user_ppc_native_view,
170 REGSET_VSX,
171 0, 32 * sizeof(double),
172 datavp);
173 #endif
174 #ifdef CONFIG_SPE
175 case PTRACE_GETEVRREGS:
176 /* Get the child spe register state. */
177 return copy_regset_to_user(child, &user_ppc_native_view,
178 REGSET_SPE, 0, 35 * sizeof(u32),
179 datavp);
180
181 case PTRACE_SETEVRREGS:
182 /* Set the child spe register state. */
183 return copy_regset_from_user(child, &user_ppc_native_view,
184 REGSET_SPE, 0, 35 * sizeof(u32),
185 datavp);
186 #endif
187
188 default:
189 ret = ptrace_request(child, request, addr, data);
190 break;
191 }
192 return ret;
193 }
194
195 void __init pt_regs_check(void);
196
197 /*
198 * Dummy function, its purpose is to break the build if struct pt_regs and
199 * struct user_pt_regs don't match.
200 */
pt_regs_check(void)201 void __init pt_regs_check(void)
202 {
203 BUILD_BUG_ON(offsetof(struct pt_regs, gpr) !=
204 offsetof(struct user_pt_regs, gpr));
205 BUILD_BUG_ON(offsetof(struct pt_regs, nip) !=
206 offsetof(struct user_pt_regs, nip));
207 BUILD_BUG_ON(offsetof(struct pt_regs, msr) !=
208 offsetof(struct user_pt_regs, msr));
209 BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
210 offsetof(struct user_pt_regs, orig_gpr3));
211 BUILD_BUG_ON(offsetof(struct pt_regs, ctr) !=
212 offsetof(struct user_pt_regs, ctr));
213 BUILD_BUG_ON(offsetof(struct pt_regs, link) !=
214 offsetof(struct user_pt_regs, link));
215 BUILD_BUG_ON(offsetof(struct pt_regs, xer) !=
216 offsetof(struct user_pt_regs, xer));
217 BUILD_BUG_ON(offsetof(struct pt_regs, ccr) !=
218 offsetof(struct user_pt_regs, ccr));
219 #ifdef __powerpc64__
220 BUILD_BUG_ON(offsetof(struct pt_regs, softe) !=
221 offsetof(struct user_pt_regs, softe));
222 #else
223 BUILD_BUG_ON(offsetof(struct pt_regs, mq) !=
224 offsetof(struct user_pt_regs, mq));
225 #endif
226 BUILD_BUG_ON(offsetof(struct pt_regs, trap) !=
227 offsetof(struct user_pt_regs, trap));
228 BUILD_BUG_ON(offsetof(struct pt_regs, dar) !=
229 offsetof(struct user_pt_regs, dar));
230 BUILD_BUG_ON(offsetof(struct pt_regs, dear) !=
231 offsetof(struct user_pt_regs, dar));
232 BUILD_BUG_ON(offsetof(struct pt_regs, dsisr) !=
233 offsetof(struct user_pt_regs, dsisr));
234 BUILD_BUG_ON(offsetof(struct pt_regs, esr) !=
235 offsetof(struct user_pt_regs, dsisr));
236 BUILD_BUG_ON(offsetof(struct pt_regs, result) !=
237 offsetof(struct user_pt_regs, result));
238
239 BUILD_BUG_ON(sizeof(struct user_pt_regs) > sizeof(struct pt_regs));
240
241 // Now check that the pt_regs offsets match the uapi #defines
242 #define CHECK_REG(_pt, _reg) \
243 BUILD_BUG_ON(_pt != (offsetof(struct user_pt_regs, _reg) / \
244 sizeof(unsigned long)));
245
246 CHECK_REG(PT_R0, gpr[0]);
247 CHECK_REG(PT_R1, gpr[1]);
248 CHECK_REG(PT_R2, gpr[2]);
249 CHECK_REG(PT_R3, gpr[3]);
250 CHECK_REG(PT_R4, gpr[4]);
251 CHECK_REG(PT_R5, gpr[5]);
252 CHECK_REG(PT_R6, gpr[6]);
253 CHECK_REG(PT_R7, gpr[7]);
254 CHECK_REG(PT_R8, gpr[8]);
255 CHECK_REG(PT_R9, gpr[9]);
256 CHECK_REG(PT_R10, gpr[10]);
257 CHECK_REG(PT_R11, gpr[11]);
258 CHECK_REG(PT_R12, gpr[12]);
259 CHECK_REG(PT_R13, gpr[13]);
260 CHECK_REG(PT_R14, gpr[14]);
261 CHECK_REG(PT_R15, gpr[15]);
262 CHECK_REG(PT_R16, gpr[16]);
263 CHECK_REG(PT_R17, gpr[17]);
264 CHECK_REG(PT_R18, gpr[18]);
265 CHECK_REG(PT_R19, gpr[19]);
266 CHECK_REG(PT_R20, gpr[20]);
267 CHECK_REG(PT_R21, gpr[21]);
268 CHECK_REG(PT_R22, gpr[22]);
269 CHECK_REG(PT_R23, gpr[23]);
270 CHECK_REG(PT_R24, gpr[24]);
271 CHECK_REG(PT_R25, gpr[25]);
272 CHECK_REG(PT_R26, gpr[26]);
273 CHECK_REG(PT_R27, gpr[27]);
274 CHECK_REG(PT_R28, gpr[28]);
275 CHECK_REG(PT_R29, gpr[29]);
276 CHECK_REG(PT_R30, gpr[30]);
277 CHECK_REG(PT_R31, gpr[31]);
278 CHECK_REG(PT_NIP, nip);
279 CHECK_REG(PT_MSR, msr);
280 CHECK_REG(PT_ORIG_R3, orig_gpr3);
281 CHECK_REG(PT_CTR, ctr);
282 CHECK_REG(PT_LNK, link);
283 CHECK_REG(PT_XER, xer);
284 CHECK_REG(PT_CCR, ccr);
285 #ifdef CONFIG_PPC64
286 CHECK_REG(PT_SOFTE, softe);
287 #else
288 CHECK_REG(PT_MQ, mq);
289 #endif
290 CHECK_REG(PT_TRAP, trap);
291 CHECK_REG(PT_DAR, dar);
292 CHECK_REG(PT_DSISR, dsisr);
293 CHECK_REG(PT_RESULT, result);
294 #undef CHECK_REG
295
296 BUILD_BUG_ON(PT_REGS_COUNT != sizeof(struct user_pt_regs) / sizeof(unsigned long));
297
298 /*
299 * PT_DSCR isn't a real reg, but it's important that it doesn't overlap the
300 * real registers.
301 */
302 BUILD_BUG_ON(PT_DSCR < sizeof(struct user_pt_regs) / sizeof(unsigned long));
303
304 // ptrace_get/put_fpr() rely on PPC32 and VSX being incompatible
305 BUILD_BUG_ON(IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_VSX));
306 }
307