aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/ptrace.c')
-rw-r--r--arch/powerpc/kernel/ptrace.c148
1 files changed, 99 insertions, 49 deletions
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index da53b0d4114b..230d5f5bfab6 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -59,6 +59,62 @@ void ptrace_disable(struct task_struct *child)
59 clear_single_step(child); 59 clear_single_step(child);
60} 60}
61 61
62/*
63 * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
64 * we mark them as obsolete now, they will be removed in a future version
65 */
66static long arch_ptrace_old(struct task_struct *child, long request, long addr,
67 long data)
68{
69 int ret = -EPERM;
70
71 switch(request) {
72 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
73 int i;
74 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
75 unsigned long __user *tmp = (unsigned long __user *)addr;
76
77 for (i = 0; i < 32; i++) {
78 ret = put_user(*reg, tmp);
79 if (ret)
80 break;
81 reg++;
82 tmp++;
83 }
84 break;
85 }
86
87 case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
88 int i;
89 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
90 unsigned long __user *tmp = (unsigned long __user *)addr;
91
92 for (i = 0; i < 32; i++) {
93 ret = get_user(*reg, tmp);
94 if (ret)
95 break;
96 reg++;
97 tmp++;
98 }
99 break;
100 }
101
102 case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
103 flush_fp_to_thread(child);
104 ret = get_fpregs((void __user *)addr, child, 0);
105 break;
106 }
107
108 case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
109 flush_fp_to_thread(child);
110 ret = set_fpregs((void __user *)addr, child, 0);
111 break;
112 }
113
114 }
115 return ret;
116}
117
62long arch_ptrace(struct task_struct *child, long request, long addr, long data) 118long arch_ptrace(struct task_struct *child, long request, long addr, long data)
63{ 119{
64 int ret = -EPERM; 120 int ret = -EPERM;
@@ -214,71 +270,58 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
214 ret = ptrace_detach(child, data); 270 ret = ptrace_detach(child, data);
215 break; 271 break;
216 272
217 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ 273#ifdef CONFIG_PPC64
218 int i; 274 case PTRACE_GETREGS64:
219 unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; 275#endif
220 unsigned long __user *tmp = (unsigned long __user *)addr; 276 case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
221 277 int ui;
222 for (i = 0; i < 32; i++) { 278 if (!access_ok(VERIFY_WRITE, (void __user *)data,
223 ret = put_user(*reg, tmp); 279 sizeof(struct pt_regs))) {
224 if (ret) 280 ret = -EIO;
225 break; 281 break;
226 reg++; 282 }
227 tmp++; 283 ret = 0;
284 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
285 ret |= __put_user(get_reg(child, ui),
286 (unsigned long __user *) data);
287 data += sizeof(long);
228 } 288 }
229 break; 289 break;
230 } 290 }
231 291
232 case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ 292#ifdef CONFIG_PPC64
233 int i; 293 case PTRACE_SETREGS64:
234 unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; 294#endif
235 unsigned long __user *tmp = (unsigned long __user *)addr; 295 case PTRACE_SETREGS: { /* Set all gp regs in the child. */
236 296 unsigned long tmp;
237 for (i = 0; i < 32; i++) { 297 int ui;
238 ret = get_user(*reg, tmp); 298 if (!access_ok(VERIFY_READ, (void __user *)data,
299 sizeof(struct pt_regs))) {
300 ret = -EIO;
301 break;
302 }
303 ret = 0;
304 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
305 ret = __get_user(tmp, (unsigned long __user *) data);
239 if (ret) 306 if (ret)
240 break; 307 break;
241 reg++; 308 put_reg(child, ui, tmp);
242 tmp++; 309 data += sizeof(long);
243 } 310 }
244 break; 311 break;
245 } 312 }
246 313
247#ifdef CONFIG_PPC64 314 case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */
248 case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
249 int i;
250 unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
251 unsigned long __user *tmp = (unsigned long __user *)addr;
252
253 flush_fp_to_thread(child); 315 flush_fp_to_thread(child);
254 316 ret = get_fpregs((void __user *)data, child, 1);
255 for (i = 0; i < 32; i++) {
256 ret = put_user(*reg, tmp);
257 if (ret)
258 break;
259 reg++;
260 tmp++;
261 }
262 break; 317 break;
263 } 318 }
264 319
265 case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ 320 case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */
266 int i;
267 unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
268 unsigned long __user *tmp = (unsigned long __user *)addr;
269
270 flush_fp_to_thread(child); 321 flush_fp_to_thread(child);
271 322 ret = set_fpregs((void __user *)data, child, 1);
272 for (i = 0; i < 32; i++) {
273 ret = get_user(*reg, tmp);
274 if (ret)
275 break;
276 reg++;
277 tmp++;
278 }
279 break; 323 break;
280 } 324 }
281#endif /* CONFIG_PPC64 */
282 325
283#ifdef CONFIG_ALTIVEC 326#ifdef CONFIG_ALTIVEC
284 case PTRACE_GETVRREGS: 327 case PTRACE_GETVRREGS:
@@ -311,11 +354,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
311 break; 354 break;
312#endif 355#endif
313 356
357 /* Old reverse args ptrace callss */
358 case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
359 case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
360 case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
361 case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
362 ret = arch_ptrace_old(child, request, addr, data);
363 break;
364
314 default: 365 default:
315 ret = ptrace_request(child, request, addr, data); 366 ret = ptrace_request(child, request, addr, data);
316 break; 367 break;
317 } 368 }
318
319 return ret; 369 return ret;
320} 370}
321 371