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