xref: /linux/arch/powerpc/kernel/ptrace/ptrace.c (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
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  */
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 
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  */
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 	CHECK_REG(PT_EXIT_FLAGS, exit_flags);
295 	#undef CHECK_REG
296 
297 	BUILD_BUG_ON(PT_REGS_COUNT != sizeof(struct user_pt_regs) / sizeof(unsigned long));
298 
299 	/*
300 	 * PT_DSCR isn't a real reg, but it's important that it doesn't overlap the
301 	 * real registers.
302 	 */
303 	BUILD_BUG_ON(PT_DSCR < sizeof(struct user_pt_regs) / sizeof(unsigned long));
304 
305 	// ptrace_get/put_fpr() rely on PPC32 and VSX being incompatible
306 	BUILD_BUG_ON(IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_VSX));
307 }
308