[POWERPC] Use generic compat_ptrace_request
[safe/jmp/linux-2.6] / arch / powerpc / kernel / ptrace32.c
1 /*
2  * ptrace for 32-bit processes running on a 64-bit kernel.
3  *
4  *  PowerPC version
5  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6  *
7  *  Derived from "arch/m68k/kernel/ptrace.c"
8  *  Copyright (C) 1994 by Hamish Macdonald
9  *  Taken from linux/kernel/ptrace.c and modified for M680x0.
10  *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
11  *
12  * Modified by Cort Dougan (cort@hq.fsmlabs.com)
13  * and Paul Mackerras (paulus@samba.org).
14  *
15  * This file is subject to the terms and conditions of the GNU General
16  * Public License.  See the file COPYING in the main directory of
17  * this archive for more details.
18  */
19
20 #include <linux/kernel.h>
21 #include <linux/sched.h>
22 #include <linux/mm.h>
23 #include <linux/smp.h>
24 #include <linux/smp_lock.h>
25 #include <linux/errno.h>
26 #include <linux/ptrace.h>
27 #include <linux/user.h>
28 #include <linux/security.h>
29 #include <linux/signal.h>
30 #include <linux/compat.h>
31
32 #include <asm/uaccess.h>
33 #include <asm/page.h>
34 #include <asm/pgtable.h>
35 #include <asm/system.h>
36
37 /*
38  * does not yet catch signals sent when the child dies.
39  * in exit.c or in signal.c.
40  */
41
42 /*
43  * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
44  * we mark them as obsolete now, they will be removed in a future version
45  */
46 static long compat_ptrace_old(struct task_struct *child, long request,
47                               long addr, long data)
48 {
49         int ret = -EPERM;
50
51         switch(request) {
52         case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
53                 int i;
54                 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
55                 unsigned int __user *tmp = (unsigned int __user *)addr;
56
57                 CHECK_FULL_REGS(child->thread.regs);
58                 for (i = 0; i < 32; i++) {
59                         ret = put_user(*reg, tmp);
60                         if (ret)
61                                 break;
62                         reg++;
63                         tmp++;
64                 }
65                 break;
66         }
67
68         case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
69                 int i;
70                 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
71                 unsigned int __user *tmp = (unsigned int __user *)addr;
72
73                 CHECK_FULL_REGS(child->thread.regs);
74                 for (i = 0; i < 32; i++) {
75                         ret = get_user(*reg, tmp);
76                         if (ret)
77                                 break;
78                         reg++;
79                         tmp++;
80                 }
81                 break;
82         }
83
84         }
85         return ret;
86 }
87
88 long compat_sys_ptrace(int request, int pid, unsigned long addr,
89                        unsigned long data)
90 {
91         struct task_struct *child;
92         int ret;
93
94         lock_kernel();
95         if (request == PTRACE_TRACEME) {
96                 ret = ptrace_traceme();
97                 goto out;
98         }
99
100         child = ptrace_get_task_struct(pid);
101         if (IS_ERR(child)) {
102                 ret = PTR_ERR(child);
103                 goto out;
104         }
105
106         if (request == PTRACE_ATTACH) {
107                 ret = ptrace_attach(child);
108                 goto out_tsk;
109         }
110
111         ret = ptrace_check_attach(child, request == PTRACE_KILL);
112         if (ret < 0)
113                 goto out_tsk;
114
115         switch (request) {
116         /*
117          * Read 4 bytes of the other process' storage
118          *  data is a pointer specifying where the user wants the
119          *      4 bytes copied into
120          *  addr is a pointer in the user's storage that contains an 8 byte
121          *      address in the other process of the 4 bytes that is to be read
122          * (this is run in a 32-bit process looking at a 64-bit process)
123          * when I and D space are separate, these will need to be fixed.
124          */
125         case PPC_PTRACE_PEEKTEXT_3264:
126         case PPC_PTRACE_PEEKDATA_3264: {
127                 u32 tmp;
128                 int copied;
129                 u32 __user * addrOthers;
130
131                 ret = -EIO;
132
133                 /* Get the addr in the other process that we want to read */
134                 if (get_user(addrOthers, (u32 __user * __user *)addr) != 0)
135                         break;
136
137                 copied = access_process_vm(child, (u64)addrOthers, &tmp,
138                                 sizeof(tmp), 0);
139                 if (copied != sizeof(tmp))
140                         break;
141                 ret = put_user(tmp, (u32 __user *)data);
142                 break;
143         }
144
145         /* Read a register (specified by ADDR) out of the "user area" */
146         case PTRACE_PEEKUSR: {
147                 int index;
148                 unsigned long tmp;
149
150                 ret = -EIO;
151                 /* convert to index and check */
152                 index = (unsigned long) addr >> 2;
153                 if ((addr & 3) || (index > PT_FPSCR32))
154                         break;
155
156                 CHECK_FULL_REGS(child->thread.regs);
157                 if (index < PT_FPR0) {
158                         tmp = ptrace_get_reg(child, index);
159                 } else {
160                         flush_fp_to_thread(child);
161                         /*
162                          * the user space code considers the floating point
163                          * to be an array of unsigned int (32 bits) - the
164                          * index passed in is based on this assumption.
165                          */
166                         tmp = ((unsigned int *)child->thread.fpr)[index - PT_FPR0];
167                 }
168                 ret = put_user((unsigned int)tmp, (u32 __user *)data);
169                 break;
170         }
171   
172         /*
173          * Read 4 bytes out of the other process' pt_regs area
174          *  data is a pointer specifying where the user wants the
175          *      4 bytes copied into
176          *  addr is the offset into the other process' pt_regs structure
177          *      that is to be read
178          * (this is run in a 32-bit process looking at a 64-bit process)
179          */
180         case PPC_PTRACE_PEEKUSR_3264: {
181                 u32 index;
182                 u32 reg32bits;
183                 u64 tmp;
184                 u32 numReg;
185                 u32 part;
186
187                 ret = -EIO;
188                 /* Determine which register the user wants */
189                 index = (u64)addr >> 2;
190                 numReg = index / 2;
191                 /* Determine which part of the register the user wants */
192                 if (index % 2)
193                         part = 1;  /* want the 2nd half of the register (right-most). */
194                 else
195                         part = 0;  /* want the 1st half of the register (left-most). */
196
197                 /* Validate the input - check to see if address is on the wrong boundary
198                  * or beyond the end of the user area
199                  */
200                 if ((addr & 3) || numReg > PT_FPSCR)
201                         break;
202
203                 CHECK_FULL_REGS(child->thread.regs);
204                 if (numReg >= PT_FPR0) {
205                         flush_fp_to_thread(child);
206                         tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
207                 } else { /* register within PT_REGS struct */
208                         tmp = ptrace_get_reg(child, numReg);
209                 } 
210                 reg32bits = ((u32*)&tmp)[part];
211                 ret = put_user(reg32bits, (u32 __user *)data);
212                 break;
213         }
214
215         /*
216          * Write 4 bytes into the other process' storage
217          *  data is the 4 bytes that the user wants written
218          *  addr is a pointer in the user's storage that contains an
219          *      8 byte address in the other process where the 4 bytes
220          *      that is to be written
221          * (this is run in a 32-bit process looking at a 64-bit process)
222          * when I and D space are separate, these will need to be fixed.
223          */
224         case PPC_PTRACE_POKETEXT_3264:
225         case PPC_PTRACE_POKEDATA_3264: {
226                 u32 tmp = data;
227                 u32 __user * addrOthers;
228
229                 /* Get the addr in the other process that we want to write into */
230                 ret = -EIO;
231                 if (get_user(addrOthers, (u32 __user * __user *)addr) != 0)
232                         break;
233                 ret = 0;
234                 if (access_process_vm(child, (u64)addrOthers, &tmp,
235                                         sizeof(tmp), 1) == sizeof(tmp))
236                         break;
237                 ret = -EIO;
238                 break;
239         }
240
241         /* write the word at location addr in the USER area */
242         case PTRACE_POKEUSR: {
243                 unsigned long index;
244
245                 ret = -EIO;
246                 /* convert to index and check */
247                 index = (unsigned long) addr >> 2;
248                 if ((addr & 3) || (index > PT_FPSCR32))
249                         break;
250
251                 CHECK_FULL_REGS(child->thread.regs);
252                 if (index < PT_FPR0) {
253                         ret = ptrace_put_reg(child, index, data);
254                 } else {
255                         flush_fp_to_thread(child);
256                         /*
257                          * the user space code considers the floating point
258                          * to be an array of unsigned int (32 bits) - the
259                          * index passed in is based on this assumption.
260                          */
261                         ((unsigned int *)child->thread.fpr)[index - PT_FPR0] = data;
262                         ret = 0;
263                 }
264                 break;
265         }
266
267         /*
268          * Write 4 bytes into the other process' pt_regs area
269          *  data is the 4 bytes that the user wants written
270          *  addr is the offset into the other process' pt_regs structure
271          *      that is to be written into
272          * (this is run in a 32-bit process looking at a 64-bit process)
273          */
274         case PPC_PTRACE_POKEUSR_3264: {
275                 u32 index;
276                 u32 numReg;
277
278                 ret = -EIO;
279                 /* Determine which register the user wants */
280                 index = (u64)addr >> 2;
281                 numReg = index / 2;
282
283                 /*
284                  * Validate the input - check to see if address is on the
285                  * wrong boundary or beyond the end of the user area
286                  */
287                 if ((addr & 3) || (numReg > PT_FPSCR))
288                         break;
289                 CHECK_FULL_REGS(child->thread.regs);
290                 if (numReg < PT_FPR0) {
291                         unsigned long freg = ptrace_get_reg(child, numReg);
292                         if (index % 2)
293                                 freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
294                         else
295                                 freg = (freg & 0xfffffffful) | (data << 32);
296                         ret = ptrace_put_reg(child, numReg, freg);
297                 } else {
298                         flush_fp_to_thread(child);
299                         ((unsigned int *)child->thread.regs)[index] = data;
300                         ret = 0;
301                 }
302                 break;
303         }
304
305         case PTRACE_GET_DEBUGREG: {
306                 ret = -EINVAL;
307                 /* We only support one DABR and no IABRS at the moment */
308                 if (addr > 0)
309                         break;
310                 ret = put_user(child->thread.dabr, (u32 __user *)data);
311                 break;
312         }
313
314         case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
315                 int ui;
316                 if (!access_ok(VERIFY_WRITE, (void __user *)data,
317                                PT_REGS_COUNT * sizeof(int))) {
318                         ret = -EIO;
319                         break;
320                 }
321                 CHECK_FULL_REGS(child->thread.regs);
322                 ret = 0;
323                 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
324                         ret |= __put_user(ptrace_get_reg(child, ui),
325                                           (unsigned int __user *) data);
326                         data += sizeof(int);
327                 }
328                 break;
329         }
330
331         case PTRACE_SETREGS: { /* Set all gp regs in the child. */
332                 unsigned long tmp;
333                 int ui;
334                 if (!access_ok(VERIFY_READ, (void __user *)data,
335                                PT_REGS_COUNT * sizeof(int))) {
336                         ret = -EIO;
337                         break;
338                 }
339                 CHECK_FULL_REGS(child->thread.regs);
340                 ret = 0;
341                 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
342                         ret = __get_user(tmp, (unsigned int __user *) data);
343                         if (ret)
344                                 break;
345                         ptrace_put_reg(child, ui, tmp);
346                         data += sizeof(int);
347                 }
348                 break;
349         }
350
351         case PTRACE_GETFPREGS:
352         case PTRACE_SETFPREGS:
353         case PTRACE_GETVRREGS:
354         case PTRACE_SETVRREGS:
355         case PTRACE_GETREGS64:
356         case PTRACE_SETREGS64:
357         case PPC_PTRACE_GETFPREGS:
358         case PPC_PTRACE_SETFPREGS:
359         case PTRACE_KILL:
360         case PTRACE_SINGLESTEP:
361         case PTRACE_DETACH:
362         case PTRACE_SET_DEBUGREG:
363         case PTRACE_SYSCALL:
364         case PTRACE_CONT:
365                 ret = arch_ptrace(child, request, addr, data);
366                 break;
367
368         /* Old reverse args ptrace callss */
369         case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
370         case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
371                 ret = compat_ptrace_old(child, request, addr, data);
372                 break;
373
374         default:
375                 ret = compat_ptrace_request(child, request, addr, data);
376                 break;
377         }
378 out_tsk:
379         put_task_struct(child);
380 out:
381         unlock_kernel();
382         return ret;
383 }