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