Blame view

arch/mips/kernel/ptrace32.c 7.94 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * This file is subject to the terms and conditions of the GNU General Public
   * License.  See the file "COPYING" in the main directory of this archive
   * for more details.
   *
   * Copyright (C) 1992 Ross Biro
   * Copyright (C) Linus Torvalds
   * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
   * Copyright (C) 1996 David S. Miller
   * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
   * Copyright (C) 1999 MIPS Technologies, Inc.
   * Copyright (C) 2000 Ulf Carlsson
   *
   * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit
   * binaries.
   */
  #include <linux/compiler.h>
5d9a76cd0   Thomas Bogendoerfer   MIPS: Use compat_...
18
  #include <linux/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
23
24
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/mm.h>
  #include <linux/errno.h>
  #include <linux/ptrace.h>
  #include <linux/smp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
  #include <linux/user.h>
  #include <linux/security.h>
  
  #include <asm/cpu.h>
e50c0a8fa   Ralf Baechle   Support the MIPS3...
29
  #include <asm/dsp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
  #include <asm/fpu.h>
  #include <asm/mipsregs.h>
101b3531a   Ralf Baechle   Protect manipulat...
32
  #include <asm/mipsmtregs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
36
37
38
39
40
41
42
  #include <asm/pgtable.h>
  #include <asm/page.h>
  #include <asm/system.h>
  #include <asm/uaccess.h>
  #include <asm/bootinfo.h>
  
  /*
   * Tracing a 32-bit process with a 64-bit strace and vice versa will not
   * work.  I don't know how to fix this.
   */
5d9a76cd0   Thomas Bogendoerfer   MIPS: Use compat_...
43
44
  long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
  			compat_ulong_t caddr, compat_ulong_t cdata)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  {
5d9a76cd0   Thomas Bogendoerfer   MIPS: Use compat_...
46
47
  	int addr = caddr;
  	int data = cdata;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  	switch (request) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50

ea3d710fe   Daniel Jacobowitz   Revise MIPS 64-bi...
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  	/*
  	 * Read 4 bytes of the other process' storage
  	 *  data is a pointer specifying where the user wants the
  	 *	4 bytes copied into
  	 *  addr is a pointer in the user's storage that contains an 8 byte
  	 *	address in the other process of the 4 bytes that is to be read
  	 * (this is run in a 32-bit process looking at a 64-bit process)
  	 * when I and D space are separate, these will need to be fixed.
  	 */
  	case PTRACE_PEEKTEXT_3264:
  	case PTRACE_PEEKDATA_3264: {
  		u32 tmp;
  		int copied;
  		u32 __user * addrOthers;
  
  		ret = -EIO;
  
  		/* Get the addr in the other process that we want to read */
  		if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
  			break;
  
  		copied = access_process_vm(child, (u64)addrOthers, &tmp,
  				sizeof(tmp), 0);
  		if (copied != sizeof(tmp))
  			break;
  		ret = put_user(tmp, (u32 __user *) (unsigned long) data);
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
  	/* Read the word at location addr in the USER area. */
  	case PTRACE_PEEKUSR: {
  		struct pt_regs *regs;
  		unsigned int tmp;
40bc9c671   Al Viro   [PATCH] mips: tas...
83
  		regs = task_pt_regs(child);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  		ret = 0;  /* Default return value. */
  
  		switch (addr) {
  		case 0 ... 31:
  			tmp = regs->regs[addr];
  			break;
  		case FPR_BASE ... FPR_BASE + 31:
  			if (tsk_used_math(child)) {
  				fpureg_t *fregs = get_fpu_regs(child);
  
  				/*
  				 * The odd registers are actually the high
  				 * order bits of the values stored in the even
  				 * registers - unless we're using r2k_switch.S.
  				 */
  				if (addr & 1)
  					tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32);
  				else
  					tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff);
  			} else {
  				tmp = -1;	/* FP not yet used  */
  			}
  			break;
  		case PC:
  			tmp = regs->cp0_epc;
  			break;
  		case CAUSE:
  			tmp = regs->cp0_cause;
  			break;
  		case BADVADDR:
  			tmp = regs->cp0_badvaddr;
  			break;
  		case MMHI:
  			tmp = regs->hi;
  			break;
  		case MMLO:
  			tmp = regs->lo;
  			break;
  		case FPC_CSR:
eae89076e   Atsushi Nemoto   [MIPS] Unify mips...
123
  			tmp = child->thread.fpu.fcr31;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
  			break;
  		case FPC_EIR: {	/* implementation / version register */
  			unsigned int flags;
41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
127
128
129
130
  #ifdef CONFIG_MIPS_MT_SMTC
  			unsigned int irqflags;
  			unsigned int mtflags;
  #endif /* CONFIG_MIPS_MT_SMTC */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131

e04582b7b   Atsushi Nemoto   [MIPS] Make sure ...
132
  			preempt_disable();
3055acb07   Atsushi Nemoto   [MIPS] Sparse: Fi...
133
  			if (!cpu_has_fpu) {
e04582b7b   Atsushi Nemoto   [MIPS] Make sure ...
134
  				preempt_enable();
3055acb07   Atsushi Nemoto   [MIPS] Sparse: Fi...
135
  				tmp = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  				break;
3055acb07   Atsushi Nemoto   [MIPS] Sparse: Fi...
137
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138

41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
139
140
141
142
143
  #ifdef CONFIG_MIPS_MT_SMTC
  			/* Read-modify-write of Status must be atomic */
  			local_irq_save(irqflags);
  			mtflags = dmt();
  #endif /* CONFIG_MIPS_MT_SMTC */
101b3531a   Ralf Baechle   Protect manipulat...
144
145
146
147
148
149
150
151
152
153
154
155
156
  			if (cpu_has_mipsmt) {
  				unsigned int vpflags = dvpe();
  				flags = read_c0_status();
  				__enable_fpu();
  				__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
  				write_c0_status(flags);
  				evpe(vpflags);
  			} else {
  				flags = read_c0_status();
  				__enable_fpu();
  				__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
  				write_c0_status(flags);
  			}
41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
157
158
159
160
  #ifdef CONFIG_MIPS_MT_SMTC
  			emt(mtflags);
  			local_irq_restore(irqflags);
  #endif /* CONFIG_MIPS_MT_SMTC */
101b3531a   Ralf Baechle   Protect manipulat...
161
  			preempt_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
  			break;
  		}
3055acb07   Atsushi Nemoto   [MIPS] Sparse: Fi...
164
165
  		case DSP_BASE ... DSP_BASE + 5: {
  			dspreg_t *dregs;
e50c0a8fa   Ralf Baechle   Support the MIPS3...
166
167
168
  			if (!cpu_has_dsp) {
  				tmp = 0;
  				ret = -EIO;
5d9a76cd0   Thomas Bogendoerfer   MIPS: Use compat_...
169
  				goto out;
e50c0a8fa   Ralf Baechle   Support the MIPS3...
170
  			}
3055acb07   Atsushi Nemoto   [MIPS] Sparse: Fi...
171
  			dregs = __get_dsp_regs(child);
6c3558527   Ralf Baechle   MIPS: DSP: elemin...
172
  			tmp = (unsigned long) (dregs[addr - DSP_BASE]);
e50c0a8fa   Ralf Baechle   Support the MIPS3...
173
  			break;
3055acb07   Atsushi Nemoto   [MIPS] Sparse: Fi...
174
  		}
e50c0a8fa   Ralf Baechle   Support the MIPS3...
175
176
177
178
  		case DSP_CONTROL:
  			if (!cpu_has_dsp) {
  				tmp = 0;
  				ret = -EIO;
5d9a76cd0   Thomas Bogendoerfer   MIPS: Use compat_...
179
  				goto out;
e50c0a8fa   Ralf Baechle   Support the MIPS3...
180
181
182
  			}
  			tmp = child->thread.dsp.dspcontrol;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
  		default:
  			tmp = 0;
  			ret = -EIO;
5d9a76cd0   Thomas Bogendoerfer   MIPS: Use compat_...
186
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  		}
3055acb07   Atsushi Nemoto   [MIPS] Sparse: Fi...
188
  		ret = put_user(tmp, (unsigned __user *) (unsigned long) data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
  		break;
  	}
ea3d710fe   Daniel Jacobowitz   Revise MIPS 64-bi...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  	/*
  	 * Write 4 bytes into the other process' storage
  	 *  data is the 4 bytes that the user wants written
  	 *  addr is a pointer in the user's storage that contains an
  	 *	8 byte address in the other process where the 4 bytes
  	 *	that is to be written
  	 * (this is run in a 32-bit process looking at a 64-bit process)
  	 * when I and D space are separate, these will need to be fixed.
  	 */
  	case PTRACE_POKETEXT_3264:
  	case PTRACE_POKEDATA_3264: {
  		u32 __user * addrOthers;
  
  		/* Get the addr in the other process that we want to write into */
  		ret = -EIO;
  		if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
  			break;
  		ret = 0;
  		if (access_process_vm(child, (u64)addrOthers, &data,
  					sizeof(data), 1) == sizeof(data))
  			break;
  		ret = -EIO;
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
  	case PTRACE_POKEUSR: {
  		struct pt_regs *regs;
  		ret = 0;
40bc9c671   Al Viro   [PATCH] mips: tas...
218
  		regs = task_pt_regs(child);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
222
223
224
225
226
227
228
  
  		switch (addr) {
  		case 0 ... 31:
  			regs->regs[addr] = data;
  			break;
  		case FPR_BASE ... FPR_BASE + 31: {
  			fpureg_t *fregs = get_fpu_regs(child);
  
  			if (!tsk_used_math(child)) {
  				/* FP not yet used  */
eae89076e   Atsushi Nemoto   [MIPS] Unify mips...
229
230
231
  				memset(&child->thread.fpu, ~0,
  				       sizeof(child->thread.fpu));
  				child->thread.fpu.fcr31 = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  			}
  			/*
  			 * The odd registers are actually the high order bits
  			 * of the values stored in the even registers - unless
  			 * we're using r2k_switch.S.
  			 */
  			if (addr & 1) {
  				fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff;
  				fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32;
  			} else {
  				fregs[addr - FPR_BASE] &= ~0xffffffffLL;
  				/* Must cast, lest sign extension fill upper
  				   bits!  */
  				fregs[addr - FPR_BASE] |= (unsigned int)data;
  			}
  			break;
  		}
  		case PC:
  			regs->cp0_epc = data;
  			break;
  		case MMHI:
  			regs->hi = data;
  			break;
  		case MMLO:
  			regs->lo = data;
  			break;
  		case FPC_CSR:
eae89076e   Atsushi Nemoto   [MIPS] Unify mips...
259
  			child->thread.fpu.fcr31 = data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
  			break;
3055acb07   Atsushi Nemoto   [MIPS] Sparse: Fi...
261
262
  		case DSP_BASE ... DSP_BASE + 5: {
  			dspreg_t *dregs;
e50c0a8fa   Ralf Baechle   Support the MIPS3...
263
264
265
266
  			if (!cpu_has_dsp) {
  				ret = -EIO;
  				break;
  			}
3055acb07   Atsushi Nemoto   [MIPS] Sparse: Fi...
267
  			dregs = __get_dsp_regs(child);
e50c0a8fa   Ralf Baechle   Support the MIPS3...
268
269
  			dregs[addr - DSP_BASE] = data;
  			break;
3055acb07   Atsushi Nemoto   [MIPS] Sparse: Fi...
270
  		}
e50c0a8fa   Ralf Baechle   Support the MIPS3...
271
272
273
274
275
276
277
  		case DSP_CONTROL:
  			if (!cpu_has_dsp) {
  				ret = -EIO;
  				break;
  			}
  			child->thread.dsp.dspcontrol = data;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
280
281
282
283
284
  		default:
  			/* The rest are not allowed. */
  			ret = -EIO;
  			break;
  		}
  		break;
  		}
ea3d710fe   Daniel Jacobowitz   Revise MIPS 64-bi...
285
  	case PTRACE_GETREGS:
62b14c24b   Atsushi Nemoto   [MIPS] Store sign...
286
  		ret = ptrace_getregs(child, (__s64 __user *) (__u64) data);
ea3d710fe   Daniel Jacobowitz   Revise MIPS 64-bi...
287
288
289
  		break;
  
  	case PTRACE_SETREGS:
62b14c24b   Atsushi Nemoto   [MIPS] Store sign...
290
  		ret = ptrace_setregs(child, (__s64 __user *) (__u64) data);
ea3d710fe   Daniel Jacobowitz   Revise MIPS 64-bi...
291
292
293
  		break;
  
  	case PTRACE_GETFPREGS:
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
294
  		ret = ptrace_getfpregs(child, (__u32 __user *) (__u64) data);
ea3d710fe   Daniel Jacobowitz   Revise MIPS 64-bi...
295
296
297
  		break;
  
  	case PTRACE_SETFPREGS:
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
298
  		ret = ptrace_setfpregs(child, (__u32 __user *) (__u64) data);
ea3d710fe   Daniel Jacobowitz   Revise MIPS 64-bi...
299
  		break;
3c37026d4   Ralf Baechle   NPTL, round one.
300
  	case PTRACE_GET_THREAD_AREA:
dc8f6029c   Al Viro   [PATCH] mips: tas...
301
  		ret = put_user(task_thread_info(child)->tp_value,
3c37026d4   Ralf Baechle   NPTL, round one.
302
303
  				(unsigned int __user *) (unsigned long) data);
  		break;
ea3d710fe   Daniel Jacobowitz   Revise MIPS 64-bi...
304
  	case PTRACE_GET_THREAD_AREA_3264:
dc8f6029c   Al Viro   [PATCH] mips: tas...
305
  		ret = put_user(task_thread_info(child)->tp_value,
ea3d710fe   Daniel Jacobowitz   Revise MIPS 64-bi...
306
307
  				(unsigned long __user *) (unsigned long) data);
  		break;
0926bf953   David Daney   MIPS: Ptrace supp...
308
309
310
311
312
313
314
315
316
  	case PTRACE_GET_WATCH_REGS:
  		ret = ptrace_get_watch_regs(child,
  			(struct pt_watch_regs __user *) (unsigned long) addr);
  		break;
  
  	case PTRACE_SET_WATCH_REGS:
  		ret = ptrace_set_watch_regs(child,
  			(struct pt_watch_regs __user *) (unsigned long) addr);
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
  	default:
797c3f322   Anirban Sinha   MIPS: 64-bit: Use...
318
  		ret = compat_ptrace_request(child, request, addr, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
320
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
  	return ret;
  }