xref: /openbmc/linux/arch/sparc/kernel/ptrace_64.c (revision e8e0929d)
1 /* ptrace.c: Sparc process tracing support.
2  *
3  * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
4  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5  *
6  * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
7  * and David Mosberger.
8  *
9  * Added Linux support -miguel (weird, eh?, the original code was meant
10  * to emulate SunOS).
11  */
12 
13 #include <linux/kernel.h>
14 #include <linux/sched.h>
15 #include <linux/mm.h>
16 #include <linux/errno.h>
17 #include <linux/ptrace.h>
18 #include <linux/user.h>
19 #include <linux/smp.h>
20 #include <linux/security.h>
21 #include <linux/seccomp.h>
22 #include <linux/audit.h>
23 #include <linux/signal.h>
24 #include <linux/regset.h>
25 #include <linux/tracehook.h>
26 #include <linux/compat.h>
27 #include <linux/elf.h>
28 
29 #include <asm/asi.h>
30 #include <asm/pgtable.h>
31 #include <asm/system.h>
32 #include <asm/uaccess.h>
33 #include <asm/psrcompat.h>
34 #include <asm/visasm.h>
35 #include <asm/spitfire.h>
36 #include <asm/page.h>
37 #include <asm/cpudata.h>
38 #include <asm/cacheflush.h>
39 
40 #include "entry.h"
41 
42 /* #define ALLOW_INIT_TRACING */
43 
44 /*
45  * Called by kernel/ptrace.c when detaching..
46  *
47  * Make sure single step bits etc are not set.
48  */
49 void ptrace_disable(struct task_struct *child)
50 {
51 	/* nothing to do */
52 }
53 
54 /* To get the necessary page struct, access_process_vm() first calls
55  * get_user_pages().  This has done a flush_dcache_page() on the
56  * accessed page.  Then our caller (copy_{to,from}_user_page()) did
57  * to memcpy to read/write the data from that page.
58  *
59  * Now, the only thing we have to do is:
60  * 1) flush the D-cache if it's possible than an illegal alias
61  *    has been created
62  * 2) flush the I-cache if this is pre-cheetah and we did a write
63  */
64 void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
65 			 unsigned long uaddr, void *kaddr,
66 			 unsigned long len, int write)
67 {
68 	BUG_ON(len > PAGE_SIZE);
69 
70 	if (tlb_type == hypervisor)
71 		return;
72 
73 	preempt_disable();
74 
75 #ifdef DCACHE_ALIASING_POSSIBLE
76 	/* If bit 13 of the kernel address we used to access the
77 	 * user page is the same as the virtual address that page
78 	 * is mapped to in the user's address space, we can skip the
79 	 * D-cache flush.
80 	 */
81 	if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
82 		unsigned long start = __pa(kaddr);
83 		unsigned long end = start + len;
84 		unsigned long dcache_line_size;
85 
86 		dcache_line_size = local_cpu_data().dcache_line_size;
87 
88 		if (tlb_type == spitfire) {
89 			for (; start < end; start += dcache_line_size)
90 				spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
91 		} else {
92 			start &= ~(dcache_line_size - 1);
93 			for (; start < end; start += dcache_line_size)
94 				__asm__ __volatile__(
95 					"stxa %%g0, [%0] %1\n\t"
96 					"membar #Sync"
97 					: /* no outputs */
98 					: "r" (start),
99 					"i" (ASI_DCACHE_INVALIDATE));
100 		}
101 	}
102 #endif
103 	if (write && tlb_type == spitfire) {
104 		unsigned long start = (unsigned long) kaddr;
105 		unsigned long end = start + len;
106 		unsigned long icache_line_size;
107 
108 		icache_line_size = local_cpu_data().icache_line_size;
109 
110 		for (; start < end; start += icache_line_size)
111 			flushi(start);
112 	}
113 
114 	preempt_enable();
115 }
116 
117 static int get_from_target(struct task_struct *target, unsigned long uaddr,
118 			   void *kbuf, int len)
119 {
120 	if (target == current) {
121 		if (copy_from_user(kbuf, (void __user *) uaddr, len))
122 			return -EFAULT;
123 	} else {
124 		int len2 = access_process_vm(target, uaddr, kbuf, len, 0);
125 		if (len2 != len)
126 			return -EFAULT;
127 	}
128 	return 0;
129 }
130 
131 static int set_to_target(struct task_struct *target, unsigned long uaddr,
132 			 void *kbuf, int len)
133 {
134 	if (target == current) {
135 		if (copy_to_user((void __user *) uaddr, kbuf, len))
136 			return -EFAULT;
137 	} else {
138 		int len2 = access_process_vm(target, uaddr, kbuf, len, 1);
139 		if (len2 != len)
140 			return -EFAULT;
141 	}
142 	return 0;
143 }
144 
145 static int regwindow64_get(struct task_struct *target,
146 			   const struct pt_regs *regs,
147 			   struct reg_window *wbuf)
148 {
149 	unsigned long rw_addr = regs->u_regs[UREG_I6];
150 
151 	if (test_tsk_thread_flag(current, TIF_32BIT)) {
152 		struct reg_window32 win32;
153 		int i;
154 
155 		if (get_from_target(target, rw_addr, &win32, sizeof(win32)))
156 			return -EFAULT;
157 		for (i = 0; i < 8; i++)
158 			wbuf->locals[i] = win32.locals[i];
159 		for (i = 0; i < 8; i++)
160 			wbuf->ins[i] = win32.ins[i];
161 	} else {
162 		rw_addr += STACK_BIAS;
163 		if (get_from_target(target, rw_addr, wbuf, sizeof(*wbuf)))
164 			return -EFAULT;
165 	}
166 
167 	return 0;
168 }
169 
170 static int regwindow64_set(struct task_struct *target,
171 			   const struct pt_regs *regs,
172 			   struct reg_window *wbuf)
173 {
174 	unsigned long rw_addr = regs->u_regs[UREG_I6];
175 
176 	if (test_tsk_thread_flag(current, TIF_32BIT)) {
177 		struct reg_window32 win32;
178 		int i;
179 
180 		for (i = 0; i < 8; i++)
181 			win32.locals[i] = wbuf->locals[i];
182 		for (i = 0; i < 8; i++)
183 			win32.ins[i] = wbuf->ins[i];
184 
185 		if (set_to_target(target, rw_addr, &win32, sizeof(win32)))
186 			return -EFAULT;
187 	} else {
188 		rw_addr += STACK_BIAS;
189 		if (set_to_target(target, rw_addr, wbuf, sizeof(*wbuf)))
190 			return -EFAULT;
191 	}
192 
193 	return 0;
194 }
195 
196 enum sparc_regset {
197 	REGSET_GENERAL,
198 	REGSET_FP,
199 };
200 
201 static int genregs64_get(struct task_struct *target,
202 			 const struct user_regset *regset,
203 			 unsigned int pos, unsigned int count,
204 			 void *kbuf, void __user *ubuf)
205 {
206 	const struct pt_regs *regs = task_pt_regs(target);
207 	int ret;
208 
209 	if (target == current)
210 		flushw_user();
211 
212 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
213 				  regs->u_regs,
214 				  0, 16 * sizeof(u64));
215 	if (!ret && count && pos < (32 * sizeof(u64))) {
216 		struct reg_window window;
217 
218 		if (regwindow64_get(target, regs, &window))
219 			return -EFAULT;
220 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
221 					  &window,
222 					  16 * sizeof(u64),
223 					  32 * sizeof(u64));
224 	}
225 
226 	if (!ret) {
227 		/* TSTATE, TPC, TNPC */
228 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
229 					  &regs->tstate,
230 					  32 * sizeof(u64),
231 					  35 * sizeof(u64));
232 	}
233 
234 	if (!ret) {
235 		unsigned long y = regs->y;
236 
237 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
238 					  &y,
239 					  35 * sizeof(u64),
240 					  36 * sizeof(u64));
241 	}
242 
243 	if (!ret) {
244 		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
245 					       36 * sizeof(u64), -1);
246 
247 	}
248 	return ret;
249 }
250 
251 static int genregs64_set(struct task_struct *target,
252 			 const struct user_regset *regset,
253 			 unsigned int pos, unsigned int count,
254 			 const void *kbuf, const void __user *ubuf)
255 {
256 	struct pt_regs *regs = task_pt_regs(target);
257 	int ret;
258 
259 	if (target == current)
260 		flushw_user();
261 
262 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
263 				 regs->u_regs,
264 				 0, 16 * sizeof(u64));
265 	if (!ret && count && pos < (32 * sizeof(u64))) {
266 		struct reg_window window;
267 
268 		if (regwindow64_get(target, regs, &window))
269 			return -EFAULT;
270 
271 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
272 					 &window,
273 					 16 * sizeof(u64),
274 					 32 * sizeof(u64));
275 
276 		if (!ret &&
277 		    regwindow64_set(target, regs, &window))
278 			return -EFAULT;
279 	}
280 
281 	if (!ret && count > 0) {
282 		unsigned long tstate;
283 
284 		/* TSTATE */
285 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
286 					 &tstate,
287 					 32 * sizeof(u64),
288 					 33 * sizeof(u64));
289 		if (!ret) {
290 			/* Only the condition codes and the "in syscall"
291 			 * state can be modified in the %tstate register.
292 			 */
293 			tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
294 			regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
295 			regs->tstate |= tstate;
296 		}
297 	}
298 
299 	if (!ret) {
300 		/* TPC, TNPC */
301 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
302 					 &regs->tpc,
303 					 33 * sizeof(u64),
304 					 35 * sizeof(u64));
305 	}
306 
307 	if (!ret) {
308 		unsigned long y;
309 
310 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
311 					 &y,
312 					 35 * sizeof(u64),
313 					 36 * sizeof(u64));
314 		if (!ret)
315 			regs->y = y;
316 	}
317 
318 	if (!ret)
319 		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
320 						36 * sizeof(u64), -1);
321 
322 	return ret;
323 }
324 
325 static int fpregs64_get(struct task_struct *target,
326 			const struct user_regset *regset,
327 			unsigned int pos, unsigned int count,
328 			void *kbuf, void __user *ubuf)
329 {
330 	const unsigned long *fpregs = task_thread_info(target)->fpregs;
331 	unsigned long fprs, fsr, gsr;
332 	int ret;
333 
334 	if (target == current)
335 		save_and_clear_fpu();
336 
337 	fprs = task_thread_info(target)->fpsaved[0];
338 
339 	if (fprs & FPRS_DL)
340 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
341 					  fpregs,
342 					  0, 16 * sizeof(u64));
343 	else
344 		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
345 					       0,
346 					       16 * sizeof(u64));
347 
348 	if (!ret) {
349 		if (fprs & FPRS_DU)
350 			ret = user_regset_copyout(&pos, &count,
351 						  &kbuf, &ubuf,
352 						  fpregs + 16,
353 						  16 * sizeof(u64),
354 						  32 * sizeof(u64));
355 		else
356 			ret = user_regset_copyout_zero(&pos, &count,
357 						       &kbuf, &ubuf,
358 						       16 * sizeof(u64),
359 						       32 * sizeof(u64));
360 	}
361 
362 	if (fprs & FPRS_FEF) {
363 		fsr = task_thread_info(target)->xfsr[0];
364 		gsr = task_thread_info(target)->gsr[0];
365 	} else {
366 		fsr = gsr = 0;
367 	}
368 
369 	if (!ret)
370 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
371 					  &fsr,
372 					  32 * sizeof(u64),
373 					  33 * sizeof(u64));
374 	if (!ret)
375 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
376 					  &gsr,
377 					  33 * sizeof(u64),
378 					  34 * sizeof(u64));
379 	if (!ret)
380 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
381 					  &fprs,
382 					  34 * sizeof(u64),
383 					  35 * sizeof(u64));
384 
385 	if (!ret)
386 		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
387 					       35 * sizeof(u64), -1);
388 
389 	return ret;
390 }
391 
392 static int fpregs64_set(struct task_struct *target,
393 			const struct user_regset *regset,
394 			unsigned int pos, unsigned int count,
395 			const void *kbuf, const void __user *ubuf)
396 {
397 	unsigned long *fpregs = task_thread_info(target)->fpregs;
398 	unsigned long fprs;
399 	int ret;
400 
401 	if (target == current)
402 		save_and_clear_fpu();
403 
404 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
405 				 fpregs,
406 				 0, 32 * sizeof(u64));
407 	if (!ret)
408 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
409 					 task_thread_info(target)->xfsr,
410 					 32 * sizeof(u64),
411 					 33 * sizeof(u64));
412 	if (!ret)
413 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
414 					 task_thread_info(target)->gsr,
415 					 33 * sizeof(u64),
416 					 34 * sizeof(u64));
417 
418 	fprs = task_thread_info(target)->fpsaved[0];
419 	if (!ret && count > 0) {
420 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
421 					 &fprs,
422 					 34 * sizeof(u64),
423 					 35 * sizeof(u64));
424 	}
425 
426 	fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
427 	task_thread_info(target)->fpsaved[0] = fprs;
428 
429 	if (!ret)
430 		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
431 						35 * sizeof(u64), -1);
432 	return ret;
433 }
434 
435 static const struct user_regset sparc64_regsets[] = {
436 	/* Format is:
437 	 * 	G0 --> G7
438 	 *	O0 --> O7
439 	 *	L0 --> L7
440 	 *	I0 --> I7
441 	 *	TSTATE, TPC, TNPC, Y
442 	 */
443 	[REGSET_GENERAL] = {
444 		.core_note_type = NT_PRSTATUS,
445 		.n = 36,
446 		.size = sizeof(u64), .align = sizeof(u64),
447 		.get = genregs64_get, .set = genregs64_set
448 	},
449 	/* Format is:
450 	 *	F0 --> F63
451 	 *	FSR
452 	 *	GSR
453 	 *	FPRS
454 	 */
455 	[REGSET_FP] = {
456 		.core_note_type = NT_PRFPREG,
457 		.n = 35,
458 		.size = sizeof(u64), .align = sizeof(u64),
459 		.get = fpregs64_get, .set = fpregs64_set
460 	},
461 };
462 
463 static const struct user_regset_view user_sparc64_view = {
464 	.name = "sparc64", .e_machine = EM_SPARCV9,
465 	.regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
466 };
467 
468 #ifdef CONFIG_COMPAT
469 static int genregs32_get(struct task_struct *target,
470 			 const struct user_regset *regset,
471 			 unsigned int pos, unsigned int count,
472 			 void *kbuf, void __user *ubuf)
473 {
474 	const struct pt_regs *regs = task_pt_regs(target);
475 	compat_ulong_t __user *reg_window;
476 	compat_ulong_t *k = kbuf;
477 	compat_ulong_t __user *u = ubuf;
478 	compat_ulong_t reg;
479 
480 	if (target == current)
481 		flushw_user();
482 
483 	pos /= sizeof(reg);
484 	count /= sizeof(reg);
485 
486 	if (kbuf) {
487 		for (; count > 0 && pos < 16; count--)
488 			*k++ = regs->u_regs[pos++];
489 
490 		reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
491 		if (target == current) {
492 			for (; count > 0 && pos < 32; count--) {
493 				if (get_user(*k++, &reg_window[pos++]))
494 					return -EFAULT;
495 			}
496 		} else {
497 			for (; count > 0 && pos < 32; count--) {
498 				if (access_process_vm(target,
499 						      (unsigned long)
500 						      &reg_window[pos],
501 						      k, sizeof(*k), 0)
502 				    != sizeof(*k))
503 					return -EFAULT;
504 				k++;
505 				pos++;
506 			}
507 		}
508 	} else {
509 		for (; count > 0 && pos < 16; count--) {
510 			if (put_user((compat_ulong_t) regs->u_regs[pos++], u++))
511 				return -EFAULT;
512 		}
513 
514 		reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
515 		if (target == current) {
516 			for (; count > 0 && pos < 32; count--) {
517 				if (get_user(reg, &reg_window[pos++]) ||
518 				    put_user(reg, u++))
519 					return -EFAULT;
520 			}
521 		} else {
522 			for (; count > 0 && pos < 32; count--) {
523 				if (access_process_vm(target,
524 						      (unsigned long)
525 						      &reg_window[pos],
526 						      &reg, sizeof(reg), 0)
527 				    != sizeof(reg))
528 					return -EFAULT;
529 				if (access_process_vm(target,
530 						      (unsigned long) u,
531 						      &reg, sizeof(reg), 1)
532 				    != sizeof(reg))
533 					return -EFAULT;
534 				pos++;
535 				u++;
536 			}
537 		}
538 	}
539 	while (count > 0) {
540 		switch (pos) {
541 		case 32: /* PSR */
542 			reg = tstate_to_psr(regs->tstate);
543 			break;
544 		case 33: /* PC */
545 			reg = regs->tpc;
546 			break;
547 		case 34: /* NPC */
548 			reg = regs->tnpc;
549 			break;
550 		case 35: /* Y */
551 			reg = regs->y;
552 			break;
553 		case 36: /* WIM */
554 		case 37: /* TBR */
555 			reg = 0;
556 			break;
557 		default:
558 			goto finish;
559 		}
560 
561 		if (kbuf)
562 			*k++ = reg;
563 		else if (put_user(reg, u++))
564 			return -EFAULT;
565 		pos++;
566 		count--;
567 	}
568 finish:
569 	pos *= sizeof(reg);
570 	count *= sizeof(reg);
571 
572 	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
573 					38 * sizeof(reg), -1);
574 }
575 
576 static int genregs32_set(struct task_struct *target,
577 			 const struct user_regset *regset,
578 			 unsigned int pos, unsigned int count,
579 			 const void *kbuf, const void __user *ubuf)
580 {
581 	struct pt_regs *regs = task_pt_regs(target);
582 	compat_ulong_t __user *reg_window;
583 	const compat_ulong_t *k = kbuf;
584 	const compat_ulong_t __user *u = ubuf;
585 	compat_ulong_t reg;
586 
587 	if (target == current)
588 		flushw_user();
589 
590 	pos /= sizeof(reg);
591 	count /= sizeof(reg);
592 
593 	if (kbuf) {
594 		for (; count > 0 && pos < 16; count--)
595 			regs->u_regs[pos++] = *k++;
596 
597 		reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
598 		if (target == current) {
599 			for (; count > 0 && pos < 32; count--) {
600 				if (put_user(*k++, &reg_window[pos++]))
601 					return -EFAULT;
602 			}
603 		} else {
604 			for (; count > 0 && pos < 32; count--) {
605 				if (access_process_vm(target,
606 						      (unsigned long)
607 						      &reg_window[pos],
608 						      (void *) k,
609 						      sizeof(*k), 1)
610 				    != sizeof(*k))
611 					return -EFAULT;
612 				k++;
613 				pos++;
614 			}
615 		}
616 	} else {
617 		for (; count > 0 && pos < 16; count--) {
618 			if (get_user(reg, u++))
619 				return -EFAULT;
620 			regs->u_regs[pos++] = reg;
621 		}
622 
623 		reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
624 		if (target == current) {
625 			for (; count > 0 && pos < 32; count--) {
626 				if (get_user(reg, u++) ||
627 				    put_user(reg, &reg_window[pos++]))
628 					return -EFAULT;
629 			}
630 		} else {
631 			for (; count > 0 && pos < 32; count--) {
632 				if (access_process_vm(target,
633 						      (unsigned long)
634 						      u,
635 						      &reg, sizeof(reg), 0)
636 				    != sizeof(reg))
637 					return -EFAULT;
638 				if (access_process_vm(target,
639 						      (unsigned long)
640 						      &reg_window[pos],
641 						      &reg, sizeof(reg), 1)
642 				    != sizeof(reg))
643 					return -EFAULT;
644 				pos++;
645 				u++;
646 			}
647 		}
648 	}
649 	while (count > 0) {
650 		unsigned long tstate;
651 
652 		if (kbuf)
653 			reg = *k++;
654 		else if (get_user(reg, u++))
655 			return -EFAULT;
656 
657 		switch (pos) {
658 		case 32: /* PSR */
659 			tstate = regs->tstate;
660 			tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
661 			tstate |= psr_to_tstate_icc(reg);
662 			if (reg & PSR_SYSCALL)
663 				tstate |= TSTATE_SYSCALL;
664 			regs->tstate = tstate;
665 			break;
666 		case 33: /* PC */
667 			regs->tpc = reg;
668 			break;
669 		case 34: /* NPC */
670 			regs->tnpc = reg;
671 			break;
672 		case 35: /* Y */
673 			regs->y = reg;
674 			break;
675 		case 36: /* WIM */
676 		case 37: /* TBR */
677 			break;
678 		default:
679 			goto finish;
680 		}
681 
682 		pos++;
683 		count--;
684 	}
685 finish:
686 	pos *= sizeof(reg);
687 	count *= sizeof(reg);
688 
689 	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
690 					 38 * sizeof(reg), -1);
691 }
692 
693 static int fpregs32_get(struct task_struct *target,
694 			const struct user_regset *regset,
695 			unsigned int pos, unsigned int count,
696 			void *kbuf, void __user *ubuf)
697 {
698 	const unsigned long *fpregs = task_thread_info(target)->fpregs;
699 	compat_ulong_t enabled;
700 	unsigned long fprs;
701 	compat_ulong_t fsr;
702 	int ret = 0;
703 
704 	if (target == current)
705 		save_and_clear_fpu();
706 
707 	fprs = task_thread_info(target)->fpsaved[0];
708 	if (fprs & FPRS_FEF) {
709 		fsr = task_thread_info(target)->xfsr[0];
710 		enabled = 1;
711 	} else {
712 		fsr = 0;
713 		enabled = 0;
714 	}
715 
716 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
717 				  fpregs,
718 				  0, 32 * sizeof(u32));
719 
720 	if (!ret)
721 		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
722 					       32 * sizeof(u32),
723 					       33 * sizeof(u32));
724 	if (!ret)
725 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
726 					  &fsr,
727 					  33 * sizeof(u32),
728 					  34 * sizeof(u32));
729 
730 	if (!ret) {
731 		compat_ulong_t val;
732 
733 		val = (enabled << 8) | (8 << 16);
734 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
735 					  &val,
736 					  34 * sizeof(u32),
737 					  35 * sizeof(u32));
738 	}
739 
740 	if (!ret)
741 		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
742 					       35 * sizeof(u32), -1);
743 
744 	return ret;
745 }
746 
747 static int fpregs32_set(struct task_struct *target,
748 			const struct user_regset *regset,
749 			unsigned int pos, unsigned int count,
750 			const void *kbuf, const void __user *ubuf)
751 {
752 	unsigned long *fpregs = task_thread_info(target)->fpregs;
753 	unsigned long fprs;
754 	int ret;
755 
756 	if (target == current)
757 		save_and_clear_fpu();
758 
759 	fprs = task_thread_info(target)->fpsaved[0];
760 
761 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
762 				 fpregs,
763 				 0, 32 * sizeof(u32));
764 	if (!ret)
765 		user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
766 					  32 * sizeof(u32),
767 					  33 * sizeof(u32));
768 	if (!ret && count > 0) {
769 		compat_ulong_t fsr;
770 		unsigned long val;
771 
772 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
773 					 &fsr,
774 					 33 * sizeof(u32),
775 					 34 * sizeof(u32));
776 		if (!ret) {
777 			val = task_thread_info(target)->xfsr[0];
778 			val &= 0xffffffff00000000UL;
779 			val |= fsr;
780 			task_thread_info(target)->xfsr[0] = val;
781 		}
782 	}
783 
784 	fprs |= (FPRS_FEF | FPRS_DL);
785 	task_thread_info(target)->fpsaved[0] = fprs;
786 
787 	if (!ret)
788 		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
789 						34 * sizeof(u32), -1);
790 	return ret;
791 }
792 
793 static const struct user_regset sparc32_regsets[] = {
794 	/* Format is:
795 	 * 	G0 --> G7
796 	 *	O0 --> O7
797 	 *	L0 --> L7
798 	 *	I0 --> I7
799 	 *	PSR, PC, nPC, Y, WIM, TBR
800 	 */
801 	[REGSET_GENERAL] = {
802 		.core_note_type = NT_PRSTATUS,
803 		.n = 38,
804 		.size = sizeof(u32), .align = sizeof(u32),
805 		.get = genregs32_get, .set = genregs32_set
806 	},
807 	/* Format is:
808 	 *	F0 --> F31
809 	 *	empty 32-bit word
810 	 *	FSR (32--bit word)
811 	 *	FPU QUEUE COUNT (8-bit char)
812 	 *	FPU QUEUE ENTRYSIZE (8-bit char)
813 	 *	FPU ENABLED (8-bit char)
814 	 *	empty 8-bit char
815 	 *	FPU QUEUE (64 32-bit ints)
816 	 */
817 	[REGSET_FP] = {
818 		.core_note_type = NT_PRFPREG,
819 		.n = 99,
820 		.size = sizeof(u32), .align = sizeof(u32),
821 		.get = fpregs32_get, .set = fpregs32_set
822 	},
823 };
824 
825 static const struct user_regset_view user_sparc32_view = {
826 	.name = "sparc", .e_machine = EM_SPARC,
827 	.regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
828 };
829 #endif /* CONFIG_COMPAT */
830 
831 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
832 {
833 #ifdef CONFIG_COMPAT
834 	if (test_tsk_thread_flag(task, TIF_32BIT))
835 		return &user_sparc32_view;
836 #endif
837 	return &user_sparc64_view;
838 }
839 
840 #ifdef CONFIG_COMPAT
841 struct compat_fps {
842 	unsigned int regs[32];
843 	unsigned int fsr;
844 	unsigned int flags;
845 	unsigned int extra;
846 	unsigned int fpqd;
847 	struct compat_fq {
848 		unsigned int insnaddr;
849 		unsigned int insn;
850 	} fpq[16];
851 };
852 
853 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
854 			compat_ulong_t caddr, compat_ulong_t cdata)
855 {
856 	const struct user_regset_view *view = task_user_regset_view(current);
857 	compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
858 	struct pt_regs32 __user *pregs;
859 	struct compat_fps __user *fps;
860 	unsigned long addr2 = caddr2;
861 	unsigned long addr = caddr;
862 	unsigned long data = cdata;
863 	int ret;
864 
865 	pregs = (struct pt_regs32 __user *) addr;
866 	fps = (struct compat_fps __user *) addr;
867 
868 	switch (request) {
869 	case PTRACE_PEEKUSR:
870 		ret = (addr != 0) ? -EIO : 0;
871 		break;
872 
873 	case PTRACE_GETREGS:
874 		ret = copy_regset_to_user(child, view, REGSET_GENERAL,
875 					  32 * sizeof(u32),
876 					  4 * sizeof(u32),
877 					  &pregs->psr);
878 		if (!ret)
879 			ret = copy_regset_to_user(child, view, REGSET_GENERAL,
880 						  1 * sizeof(u32),
881 						  15 * sizeof(u32),
882 						  &pregs->u_regs[0]);
883 		break;
884 
885 	case PTRACE_SETREGS:
886 		ret = copy_regset_from_user(child, view, REGSET_GENERAL,
887 					    32 * sizeof(u32),
888 					    4 * sizeof(u32),
889 					    &pregs->psr);
890 		if (!ret)
891 			ret = copy_regset_from_user(child, view, REGSET_GENERAL,
892 						    1 * sizeof(u32),
893 						    15 * sizeof(u32),
894 						    &pregs->u_regs[0]);
895 		break;
896 
897 	case PTRACE_GETFPREGS:
898 		ret = copy_regset_to_user(child, view, REGSET_FP,
899 					  0 * sizeof(u32),
900 					  32 * sizeof(u32),
901 					  &fps->regs[0]);
902 		if (!ret)
903 			ret = copy_regset_to_user(child, view, REGSET_FP,
904 						  33 * sizeof(u32),
905 						  1 * sizeof(u32),
906 						  &fps->fsr);
907 		if (!ret) {
908 			if (__put_user(0, &fps->flags) ||
909 			    __put_user(0, &fps->extra) ||
910 			    __put_user(0, &fps->fpqd) ||
911 			    clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
912 				ret = -EFAULT;
913 		}
914 		break;
915 
916 	case PTRACE_SETFPREGS:
917 		ret = copy_regset_from_user(child, view, REGSET_FP,
918 					    0 * sizeof(u32),
919 					    32 * sizeof(u32),
920 					    &fps->regs[0]);
921 		if (!ret)
922 			ret = copy_regset_from_user(child, view, REGSET_FP,
923 						    33 * sizeof(u32),
924 						    1 * sizeof(u32),
925 						    &fps->fsr);
926 		break;
927 
928 	case PTRACE_READTEXT:
929 	case PTRACE_READDATA:
930 		ret = ptrace_readdata(child, addr,
931 				      (char __user *)addr2, data);
932 		if (ret == data)
933 			ret = 0;
934 		else if (ret >= 0)
935 			ret = -EIO;
936 		break;
937 
938 	case PTRACE_WRITETEXT:
939 	case PTRACE_WRITEDATA:
940 		ret = ptrace_writedata(child, (char __user *) addr2,
941 				       addr, data);
942 		if (ret == data)
943 			ret = 0;
944 		else if (ret >= 0)
945 			ret = -EIO;
946 		break;
947 
948 	default:
949 		if (request == PTRACE_SPARC_DETACH)
950 			request = PTRACE_DETACH;
951 		ret = compat_ptrace_request(child, request, addr, data);
952 		break;
953 	}
954 
955 	return ret;
956 }
957 #endif /* CONFIG_COMPAT */
958 
959 struct fps {
960 	unsigned int regs[64];
961 	unsigned long fsr;
962 };
963 
964 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
965 {
966 	const struct user_regset_view *view = task_user_regset_view(current);
967 	unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
968 	struct pt_regs __user *pregs;
969 	struct fps __user *fps;
970 	int ret;
971 
972 	pregs = (struct pt_regs __user *) (unsigned long) addr;
973 	fps = (struct fps __user *) (unsigned long) addr;
974 
975 	switch (request) {
976 	case PTRACE_PEEKUSR:
977 		ret = (addr != 0) ? -EIO : 0;
978 		break;
979 
980 	case PTRACE_GETREGS64:
981 		ret = copy_regset_to_user(child, view, REGSET_GENERAL,
982 					  1 * sizeof(u64),
983 					  15 * sizeof(u64),
984 					  &pregs->u_regs[0]);
985 		if (!ret) {
986 			/* XXX doesn't handle 'y' register correctly XXX */
987 			ret = copy_regset_to_user(child, view, REGSET_GENERAL,
988 						  32 * sizeof(u64),
989 						  4 * sizeof(u64),
990 						  &pregs->tstate);
991 		}
992 		break;
993 
994 	case PTRACE_SETREGS64:
995 		ret = copy_regset_from_user(child, view, REGSET_GENERAL,
996 					    1 * sizeof(u64),
997 					    15 * sizeof(u64),
998 					    &pregs->u_regs[0]);
999 		if (!ret) {
1000 			/* XXX doesn't handle 'y' register correctly XXX */
1001 			ret = copy_regset_from_user(child, view, REGSET_GENERAL,
1002 						    32 * sizeof(u64),
1003 						    4 * sizeof(u64),
1004 						    &pregs->tstate);
1005 		}
1006 		break;
1007 
1008 	case PTRACE_GETFPREGS64:
1009 		ret = copy_regset_to_user(child, view, REGSET_FP,
1010 					  0 * sizeof(u64),
1011 					  33 * sizeof(u64),
1012 					  fps);
1013 		break;
1014 
1015 	case PTRACE_SETFPREGS64:
1016 		ret = copy_regset_from_user(child, view, REGSET_FP,
1017 					  0 * sizeof(u64),
1018 					  33 * sizeof(u64),
1019 					  fps);
1020 		break;
1021 
1022 	case PTRACE_READTEXT:
1023 	case PTRACE_READDATA:
1024 		ret = ptrace_readdata(child, addr,
1025 				      (char __user *)addr2, data);
1026 		if (ret == data)
1027 			ret = 0;
1028 		else if (ret >= 0)
1029 			ret = -EIO;
1030 		break;
1031 
1032 	case PTRACE_WRITETEXT:
1033 	case PTRACE_WRITEDATA:
1034 		ret = ptrace_writedata(child, (char __user *) addr2,
1035 				       addr, data);
1036 		if (ret == data)
1037 			ret = 0;
1038 		else if (ret >= 0)
1039 			ret = -EIO;
1040 		break;
1041 
1042 	default:
1043 		if (request == PTRACE_SPARC_DETACH)
1044 			request = PTRACE_DETACH;
1045 		ret = ptrace_request(child, request, addr, data);
1046 		break;
1047 	}
1048 
1049 	return ret;
1050 }
1051 
1052 asmlinkage int syscall_trace_enter(struct pt_regs *regs)
1053 {
1054 	int ret = 0;
1055 
1056 	/* do the secure computing check first */
1057 	secure_computing(regs->u_regs[UREG_G1]);
1058 
1059 	if (test_thread_flag(TIF_SYSCALL_TRACE))
1060 		ret = tracehook_report_syscall_entry(regs);
1061 
1062 	if (unlikely(current->audit_context) && !ret)
1063 		audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
1064 				     AUDIT_ARCH_SPARC :
1065 				     AUDIT_ARCH_SPARC64),
1066 				    regs->u_regs[UREG_G1],
1067 				    regs->u_regs[UREG_I0],
1068 				    regs->u_regs[UREG_I1],
1069 				    regs->u_regs[UREG_I2],
1070 				    regs->u_regs[UREG_I3]);
1071 
1072 	return ret;
1073 }
1074 
1075 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
1076 {
1077 	if (unlikely(current->audit_context)) {
1078 		unsigned long tstate = regs->tstate;
1079 		int result = AUDITSC_SUCCESS;
1080 
1081 		if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
1082 			result = AUDITSC_FAILURE;
1083 
1084 		audit_syscall_exit(result, regs->u_regs[UREG_I0]);
1085 	}
1086 
1087 	if (test_thread_flag(TIF_SYSCALL_TRACE))
1088 		tracehook_report_syscall_exit(regs, 0);
1089 }
1090