aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/ptrace32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/ptrace32.c')
-rw-r--r--arch/mips/kernel/ptrace32.c150
1 files changed, 145 insertions, 5 deletions
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index eee207969c21..9a9b04972132 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -24,17 +24,24 @@
24#include <linux/smp_lock.h> 24#include <linux/smp_lock.h>
25#include <linux/user.h> 25#include <linux/user.h>
26#include <linux/security.h> 26#include <linux/security.h>
27#include <linux/signal.h>
28 27
29#include <asm/cpu.h> 28#include <asm/cpu.h>
29#include <asm/dsp.h>
30#include <asm/fpu.h> 30#include <asm/fpu.h>
31#include <asm/mipsregs.h> 31#include <asm/mipsregs.h>
32#include <asm/mipsmtregs.h>
32#include <asm/pgtable.h> 33#include <asm/pgtable.h>
33#include <asm/page.h> 34#include <asm/page.h>
34#include <asm/system.h> 35#include <asm/system.h>
35#include <asm/uaccess.h> 36#include <asm/uaccess.h>
36#include <asm/bootinfo.h> 37#include <asm/bootinfo.h>
37 38
39int ptrace_getregs (struct task_struct *child, __s64 __user *data);
40int ptrace_setregs (struct task_struct *child, __s64 __user *data);
41
42int ptrace_getfpregs (struct task_struct *child, __u32 __user *data);
43int ptrace_setfpregs (struct task_struct *child, __u32 __user *data);
44
38/* 45/*
39 * Tracing a 32-bit process with a 64-bit strace and vice versa will not 46 * Tracing a 32-bit process with a 64-bit strace and vice versa will not
40 * work. I don't know how to fix this. 47 * work. I don't know how to fix this.
@@ -99,6 +106,35 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
99 break; 106 break;
100 } 107 }
101 108
109 /*
110 * Read 4 bytes of the other process' storage
111 * data is a pointer specifying where the user wants the
112 * 4 bytes copied into
113 * addr is a pointer in the user's storage that contains an 8 byte
114 * address in the other process of the 4 bytes that is to be read
115 * (this is run in a 32-bit process looking at a 64-bit process)
116 * when I and D space are separate, these will need to be fixed.
117 */
118 case PTRACE_PEEKTEXT_3264:
119 case PTRACE_PEEKDATA_3264: {
120 u32 tmp;
121 int copied;
122 u32 __user * addrOthers;
123
124 ret = -EIO;
125
126 /* Get the addr in the other process that we want to read */
127 if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
128 break;
129
130 copied = access_process_vm(child, (u64)addrOthers, &tmp,
131 sizeof(tmp), 0);
132 if (copied != sizeof(tmp))
133 break;
134 ret = put_user(tmp, (u32 __user *) (unsigned long) data);
135 break;
136 }
137
102 /* Read the word at location addr in the USER area. */ 138 /* Read the word at location addr in the USER area. */
103 case PTRACE_PEEKUSR: { 139 case PTRACE_PEEKUSR: {
104 struct pt_regs *regs; 140 struct pt_regs *regs;
@@ -156,12 +192,44 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
156 if (!cpu_has_fpu) 192 if (!cpu_has_fpu)
157 break; 193 break;
158 194
159 flags = read_c0_status(); 195 preempt_disable();
160 __enable_fpu(); 196 if (cpu_has_mipsmt) {
161 __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); 197 unsigned int vpflags = dvpe();
162 write_c0_status(flags); 198 flags = read_c0_status();
199 __enable_fpu();
200 __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
201 write_c0_status(flags);
202 evpe(vpflags);
203 } else {
204 flags = read_c0_status();
205 __enable_fpu();
206 __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
207 write_c0_status(flags);
208 }
209 preempt_enable();
163 break; 210 break;
164 } 211 }
212 case DSP_BASE ... DSP_BASE + 5:
213 if (!cpu_has_dsp) {
214 tmp = 0;
215 ret = -EIO;
216 goto out_tsk;
217 }
218 if (child->thread.dsp.used_dsp) {
219 dspreg_t *dregs = __get_dsp_regs(child);
220 tmp = (unsigned long) (dregs[addr - DSP_BASE]);
221 } else {
222 tmp = -1; /* DSP registers yet used */
223 }
224 break;
225 case DSP_CONTROL:
226 if (!cpu_has_dsp) {
227 tmp = 0;
228 ret = -EIO;
229 goto out_tsk;
230 }
231 tmp = child->thread.dsp.dspcontrol;
232 break;
165 default: 233 default:
166 tmp = 0; 234 tmp = 0;
167 ret = -EIO; 235 ret = -EIO;
@@ -181,6 +249,31 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
181 ret = -EIO; 249 ret = -EIO;
182 break; 250 break;
183 251
252 /*
253 * Write 4 bytes into the other process' storage
254 * data is the 4 bytes that the user wants written
255 * addr is a pointer in the user's storage that contains an
256 * 8 byte address in the other process where the 4 bytes
257 * that is to be written
258 * (this is run in a 32-bit process looking at a 64-bit process)
259 * when I and D space are separate, these will need to be fixed.
260 */
261 case PTRACE_POKETEXT_3264:
262 case PTRACE_POKEDATA_3264: {
263 u32 __user * addrOthers;
264
265 /* Get the addr in the other process that we want to write into */
266 ret = -EIO;
267 if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
268 break;
269 ret = 0;
270 if (access_process_vm(child, (u64)addrOthers, &data,
271 sizeof(data), 1) == sizeof(data))
272 break;
273 ret = -EIO;
274 break;
275 }
276
184 case PTRACE_POKEUSR: { 277 case PTRACE_POKEUSR: {
185 struct pt_regs *regs; 278 struct pt_regs *regs;
186 ret = 0; 279 ret = 0;
@@ -231,6 +324,22 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
231 else 324 else
232 child->thread.fpu.soft.fcr31 = data; 325 child->thread.fpu.soft.fcr31 = data;
233 break; 326 break;
327 case DSP_BASE ... DSP_BASE + 5:
328 if (!cpu_has_dsp) {
329 ret = -EIO;
330 break;
331 }
332
333 dspreg_t *dregs = __get_dsp_regs(child);
334 dregs[addr - DSP_BASE] = data;
335 break;
336 case DSP_CONTROL:
337 if (!cpu_has_dsp) {
338 ret = -EIO;
339 break;
340 }
341 child->thread.dsp.dspcontrol = data;
342 break;
234 default: 343 default:
235 /* The rest are not allowed. */ 344 /* The rest are not allowed. */
236 ret = -EIO; 345 ret = -EIO;
@@ -239,6 +348,22 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
239 break; 348 break;
240 } 349 }
241 350
351 case PTRACE_GETREGS:
352 ret = ptrace_getregs (child, (__u64 __user *) (__u64) data);
353 break;
354
355 case PTRACE_SETREGS:
356 ret = ptrace_setregs (child, (__u64 __user *) (__u64) data);
357 break;
358
359 case PTRACE_GETFPREGS:
360 ret = ptrace_getfpregs (child, (__u32 __user *) (__u64) data);
361 break;
362
363 case PTRACE_SETFPREGS:
364 ret = ptrace_setfpregs (child, (__u32 __user *) (__u64) data);
365 break;
366
242 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ 367 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
243 case PTRACE_CONT: { /* restart after signal. */ 368 case PTRACE_CONT: { /* restart after signal. */
244 ret = -EIO; 369 ret = -EIO;
@@ -269,10 +394,25 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
269 wake_up_process(child); 394 wake_up_process(child);
270 break; 395 break;
271 396
397 case PTRACE_GET_THREAD_AREA:
398 ret = put_user(child->thread_info->tp_value,
399 (unsigned int __user *) (unsigned long) data);
400 break;
401
272 case PTRACE_DETACH: /* detach a process that was attached. */ 402 case PTRACE_DETACH: /* detach a process that was attached. */
273 ret = ptrace_detach(child, data); 403 ret = ptrace_detach(child, data);
274 break; 404 break;
275 405
406 case PTRACE_GETEVENTMSG:
407 ret = put_user(child->ptrace_message,
408 (unsigned int __user *) (unsigned long) data);
409 break;
410
411 case PTRACE_GET_THREAD_AREA_3264:
412 ret = put_user(child->thread_info->tp_value,
413 (unsigned long __user *) (unsigned long) data);
414 break;
415
276 default: 416 default:
277 ret = ptrace_request(child, request, addr, data); 417 ret = ptrace_request(child, request, addr, data);
278 break; 418 break;