xref: /openbmc/linux/arch/arm/kernel/ptrace.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  linux/arch/arm/kernel/ptrace.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  By Ross Biro 1/23/92
61da177e4SLinus Torvalds  * edited by Linus Torvalds
71da177e4SLinus Torvalds  * ARM modifications Copyright (C) 2000 Russell King
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds #include <linux/kernel.h>
103f07c014SIngo Molnar #include <linux/sched/signal.h>
1168db0cf1SIngo Molnar #include <linux/sched/task_stack.h>
121da177e4SLinus Torvalds #include <linux/mm.h>
13ce8b9d25SPaul Gortmaker #include <linux/elf.h>
141da177e4SLinus Torvalds #include <linux/smp.h>
151da177e4SLinus Torvalds #include <linux/ptrace.h>
161da177e4SLinus Torvalds #include <linux/user.h>
171da177e4SLinus Torvalds #include <linux/security.h>
181da177e4SLinus Torvalds #include <linux/init.h>
197ed20e1aSJesper Juhl #include <linux/signal.h>
2033fa9b13SRussell King #include <linux/uaccess.h>
21864232faSWill Deacon #include <linux/perf_event.h>
22864232faSWill Deacon #include <linux/hw_breakpoint.h>
235be6f62bSDave Martin #include <linux/regset.h>
245180bb39SEric Paris #include <linux/audit.h>
25ad82cc08SWill Deacon #include <linux/unistd.h>
261da177e4SLinus Torvalds 
274e57a4ddSArnd Bergmann #include <asm/syscall.h>
281da177e4SLinus Torvalds #include <asm/traps.h>
291da177e4SLinus Torvalds 
301f66e06fSWade Farnsworth #define CREATE_TRACE_POINTS
311f66e06fSWade Farnsworth #include <trace/events/syscalls.h>
321f66e06fSWade Farnsworth 
331da177e4SLinus Torvalds #define REG_PC	15
341da177e4SLinus Torvalds #define REG_PSR	16
351da177e4SLinus Torvalds /*
361da177e4SLinus Torvalds  * does not yet catch signals sent when the child dies.
371da177e4SLinus Torvalds  * in exit.c or in signal.c.
381da177e4SLinus Torvalds  */
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds #if 0
411da177e4SLinus Torvalds /*
421da177e4SLinus Torvalds  * Breakpoint SWI instruction: SWI &9F0001
431da177e4SLinus Torvalds  */
441da177e4SLinus Torvalds #define BREAKINST_ARM	0xef9f0001
451da177e4SLinus Torvalds #define BREAKINST_THUMB	0xdf00		/* fill this in later */
461da177e4SLinus Torvalds #else
471da177e4SLinus Torvalds /*
481da177e4SLinus Torvalds  * New breakpoints - use an undefined instruction.  The ARM architecture
491da177e4SLinus Torvalds  * reference manual guarantees that the following instruction space
501da177e4SLinus Torvalds  * will produce an undefined instruction exception on all CPUs:
511da177e4SLinus Torvalds  *
521da177e4SLinus Torvalds  *  ARM:   xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
531da177e4SLinus Torvalds  *  Thumb: 1101 1110 xxxx xxxx
541da177e4SLinus Torvalds  */
551da177e4SLinus Torvalds #define BREAKINST_ARM	0xe7f001f0
561da177e4SLinus Torvalds #define BREAKINST_THUMB	0xde01
571da177e4SLinus Torvalds #endif
581da177e4SLinus Torvalds 
59e513f8bfSWill Deacon struct pt_regs_offset {
60e513f8bfSWill Deacon 	const char *name;
61e513f8bfSWill Deacon 	int offset;
62e513f8bfSWill Deacon };
63e513f8bfSWill Deacon 
64e513f8bfSWill Deacon #define REG_OFFSET_NAME(r) \
65e513f8bfSWill Deacon 	{.name = #r, .offset = offsetof(struct pt_regs, ARM_##r)}
66e513f8bfSWill Deacon #define REG_OFFSET_END {.name = NULL, .offset = 0}
67e513f8bfSWill Deacon 
68e513f8bfSWill Deacon static const struct pt_regs_offset regoffset_table[] = {
69e513f8bfSWill Deacon 	REG_OFFSET_NAME(r0),
70e513f8bfSWill Deacon 	REG_OFFSET_NAME(r1),
71e513f8bfSWill Deacon 	REG_OFFSET_NAME(r2),
72e513f8bfSWill Deacon 	REG_OFFSET_NAME(r3),
73e513f8bfSWill Deacon 	REG_OFFSET_NAME(r4),
74e513f8bfSWill Deacon 	REG_OFFSET_NAME(r5),
75e513f8bfSWill Deacon 	REG_OFFSET_NAME(r6),
76e513f8bfSWill Deacon 	REG_OFFSET_NAME(r7),
77e513f8bfSWill Deacon 	REG_OFFSET_NAME(r8),
78e513f8bfSWill Deacon 	REG_OFFSET_NAME(r9),
79e513f8bfSWill Deacon 	REG_OFFSET_NAME(r10),
80e513f8bfSWill Deacon 	REG_OFFSET_NAME(fp),
81e513f8bfSWill Deacon 	REG_OFFSET_NAME(ip),
82e513f8bfSWill Deacon 	REG_OFFSET_NAME(sp),
83e513f8bfSWill Deacon 	REG_OFFSET_NAME(lr),
84e513f8bfSWill Deacon 	REG_OFFSET_NAME(pc),
85e513f8bfSWill Deacon 	REG_OFFSET_NAME(cpsr),
86e513f8bfSWill Deacon 	REG_OFFSET_NAME(ORIG_r0),
87e513f8bfSWill Deacon 	REG_OFFSET_END,
88e513f8bfSWill Deacon };
89e513f8bfSWill Deacon 
90e513f8bfSWill Deacon /**
91e513f8bfSWill Deacon  * regs_query_register_offset() - query register offset from its name
92e513f8bfSWill Deacon  * @name:	the name of a register
93e513f8bfSWill Deacon  *
94e513f8bfSWill Deacon  * regs_query_register_offset() returns the offset of a register in struct
95e513f8bfSWill Deacon  * pt_regs from its name. If the name is invalid, this returns -EINVAL;
96e513f8bfSWill Deacon  */
regs_query_register_offset(const char * name)97e513f8bfSWill Deacon int regs_query_register_offset(const char *name)
98e513f8bfSWill Deacon {
99e513f8bfSWill Deacon 	const struct pt_regs_offset *roff;
100e513f8bfSWill Deacon 	for (roff = regoffset_table; roff->name != NULL; roff++)
101e513f8bfSWill Deacon 		if (!strcmp(roff->name, name))
102e513f8bfSWill Deacon 			return roff->offset;
103e513f8bfSWill Deacon 	return -EINVAL;
104e513f8bfSWill Deacon }
105e513f8bfSWill Deacon 
106e513f8bfSWill Deacon /**
107e513f8bfSWill Deacon  * regs_query_register_name() - query register name from its offset
108e513f8bfSWill Deacon  * @offset:	the offset of a register in struct pt_regs.
109e513f8bfSWill Deacon  *
110e513f8bfSWill Deacon  * regs_query_register_name() returns the name of a register from its
111e513f8bfSWill Deacon  * offset in struct pt_regs. If the @offset is invalid, this returns NULL;
112e513f8bfSWill Deacon  */
regs_query_register_name(unsigned int offset)113e513f8bfSWill Deacon const char *regs_query_register_name(unsigned int offset)
114e513f8bfSWill Deacon {
115e513f8bfSWill Deacon 	const struct pt_regs_offset *roff;
116e513f8bfSWill Deacon 	for (roff = regoffset_table; roff->name != NULL; roff++)
117e513f8bfSWill Deacon 		if (roff->offset == offset)
118e513f8bfSWill Deacon 			return roff->name;
119e513f8bfSWill Deacon 	return NULL;
120e513f8bfSWill Deacon }
121e513f8bfSWill Deacon 
122e513f8bfSWill Deacon /**
123e513f8bfSWill Deacon  * regs_within_kernel_stack() - check the address in the stack
124e513f8bfSWill Deacon  * @regs:      pt_regs which contains kernel stack pointer.
125e513f8bfSWill Deacon  * @addr:      address which is checked.
126e513f8bfSWill Deacon  *
127e513f8bfSWill Deacon  * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
128e513f8bfSWill Deacon  * If @addr is within the kernel stack, it returns true. If not, returns false.
129e513f8bfSWill Deacon  */
regs_within_kernel_stack(struct pt_regs * regs,unsigned long addr)130e513f8bfSWill Deacon bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
131e513f8bfSWill Deacon {
132e513f8bfSWill Deacon 	return ((addr & ~(THREAD_SIZE - 1))  ==
133e513f8bfSWill Deacon 		(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
134e513f8bfSWill Deacon }
135e513f8bfSWill Deacon 
136e513f8bfSWill Deacon /**
137e513f8bfSWill Deacon  * regs_get_kernel_stack_nth() - get Nth entry of the stack
138e513f8bfSWill Deacon  * @regs:	pt_regs which contains kernel stack pointer.
139e513f8bfSWill Deacon  * @n:		stack entry number.
140e513f8bfSWill Deacon  *
141e513f8bfSWill Deacon  * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
142e513f8bfSWill Deacon  * is specified by @regs. If the @n th entry is NOT in the kernel stack,
143e513f8bfSWill Deacon  * this returns 0.
144e513f8bfSWill Deacon  */
regs_get_kernel_stack_nth(struct pt_regs * regs,unsigned int n)145e513f8bfSWill Deacon unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
146e513f8bfSWill Deacon {
147e513f8bfSWill Deacon 	unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
148e513f8bfSWill Deacon 	addr += n;
149e513f8bfSWill Deacon 	if (regs_within_kernel_stack(regs, (unsigned long)addr))
150e513f8bfSWill Deacon 		return *addr;
151e513f8bfSWill Deacon 	else
152e513f8bfSWill Deacon 		return 0;
153e513f8bfSWill Deacon }
154e513f8bfSWill Deacon 
1551da177e4SLinus Torvalds /*
1561da177e4SLinus Torvalds  * this routine will get a word off of the processes privileged stack.
1571da177e4SLinus Torvalds  * the offset is how far from the base addr as stored in the THREAD.
1581da177e4SLinus Torvalds  * this routine assumes that all the privileged stacks are in our
1591da177e4SLinus Torvalds  * data space.
1601da177e4SLinus Torvalds  */
get_user_reg(struct task_struct * task,int offset)1611da177e4SLinus Torvalds static inline long get_user_reg(struct task_struct *task, int offset)
1621da177e4SLinus Torvalds {
163815d5ec8SAl Viro 	return task_pt_regs(task)->uregs[offset];
1641da177e4SLinus Torvalds }
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds /*
1671da177e4SLinus Torvalds  * this routine will put a word on the processes privileged stack.
1681da177e4SLinus Torvalds  * the offset is how far from the base addr as stored in the THREAD.
1691da177e4SLinus Torvalds  * this routine assumes that all the privileged stacks are in our
1701da177e4SLinus Torvalds  * data space.
1711da177e4SLinus Torvalds  */
1721da177e4SLinus Torvalds static inline int
put_user_reg(struct task_struct * task,int offset,long data)1731da177e4SLinus Torvalds put_user_reg(struct task_struct *task, int offset, long data)
1741da177e4SLinus Torvalds {
175815d5ec8SAl Viro 	struct pt_regs newregs, *regs = task_pt_regs(task);
1761da177e4SLinus Torvalds 	int ret = -EINVAL;
1771da177e4SLinus Torvalds 
1781da177e4SLinus Torvalds 	newregs = *regs;
1791da177e4SLinus Torvalds 	newregs.uregs[offset] = data;
1801da177e4SLinus Torvalds 
1811da177e4SLinus Torvalds 	if (valid_user_regs(&newregs)) {
1821da177e4SLinus Torvalds 		regs->uregs[offset] = data;
1831da177e4SLinus Torvalds 		ret = 0;
1841da177e4SLinus Torvalds 	}
1851da177e4SLinus Torvalds 
1861da177e4SLinus Torvalds 	return ret;
1871da177e4SLinus Torvalds }
1881da177e4SLinus Torvalds 
1891da177e4SLinus Torvalds /*
1901da177e4SLinus Torvalds  * Called by kernel/ptrace.c when detaching..
1911da177e4SLinus Torvalds  */
ptrace_disable(struct task_struct * child)1921da177e4SLinus Torvalds void ptrace_disable(struct task_struct *child)
1931da177e4SLinus Torvalds {
194425fc47aSWill Deacon 	/* Nothing to do. */
1951da177e4SLinus Torvalds }
1961da177e4SLinus Torvalds 
1971da177e4SLinus Torvalds /*
1981da177e4SLinus Torvalds  * Handle hitting a breakpoint.
1991da177e4SLinus Torvalds  */
ptrace_break(struct pt_regs * regs)200e9a06509SEric W. Biederman void ptrace_break(struct pt_regs *regs)
2011da177e4SLinus Torvalds {
2023ee6a449SEric W. Biederman 	force_sig_fault(SIGTRAP, TRAP_BRKPT,
2032e1661d2SEric W. Biederman 			(void __user *)instruction_pointer(regs));
2041da177e4SLinus Torvalds }
2051da177e4SLinus Torvalds 
break_trap(struct pt_regs * regs,unsigned int instr)2061da177e4SLinus Torvalds static int break_trap(struct pt_regs *regs, unsigned int instr)
2071da177e4SLinus Torvalds {
208e9a06509SEric W. Biederman 	ptrace_break(regs);
2091da177e4SLinus Torvalds 	return 0;
2101da177e4SLinus Torvalds }
2111da177e4SLinus Torvalds 
2121da177e4SLinus Torvalds static struct undef_hook arm_break_hook = {
2131da177e4SLinus Torvalds 	.instr_mask	= 0x0fffffff,
2141da177e4SLinus Torvalds 	.instr_val	= 0x07f001f0,
2151da177e4SLinus Torvalds 	.cpsr_mask	= PSR_T_BIT,
2161da177e4SLinus Torvalds 	.cpsr_val	= 0,
2171da177e4SLinus Torvalds 	.fn		= break_trap,
2181da177e4SLinus Torvalds };
2191da177e4SLinus Torvalds 
2201da177e4SLinus Torvalds static struct undef_hook thumb_break_hook = {
2213866f217SFredrik Strupe 	.instr_mask	= 0xffffffff,
2223866f217SFredrik Strupe 	.instr_val	= 0x0000de01,
2231da177e4SLinus Torvalds 	.cpsr_mask	= PSR_T_BIT,
2241da177e4SLinus Torvalds 	.cpsr_val	= PSR_T_BIT,
2251da177e4SLinus Torvalds 	.fn		= break_trap,
2261da177e4SLinus Torvalds };
2271da177e4SLinus Torvalds 
228d23bc1b3SDaniel Jacobowitz static struct undef_hook thumb2_break_hook = {
229592201a9SJon Medhurst 	.instr_mask	= 0xffffffff,
230592201a9SJon Medhurst 	.instr_val	= 0xf7f0a000,
231d23bc1b3SDaniel Jacobowitz 	.cpsr_mask	= PSR_T_BIT,
232d23bc1b3SDaniel Jacobowitz 	.cpsr_val	= PSR_T_BIT,
233592201a9SJon Medhurst 	.fn		= break_trap,
234d23bc1b3SDaniel Jacobowitz };
235d23bc1b3SDaniel Jacobowitz 
ptrace_break_init(void)2361da177e4SLinus Torvalds static int __init ptrace_break_init(void)
2371da177e4SLinus Torvalds {
2381da177e4SLinus Torvalds 	register_undef_hook(&arm_break_hook);
2391da177e4SLinus Torvalds 	register_undef_hook(&thumb_break_hook);
240d23bc1b3SDaniel Jacobowitz 	register_undef_hook(&thumb2_break_hook);
2411da177e4SLinus Torvalds 	return 0;
2421da177e4SLinus Torvalds }
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds core_initcall(ptrace_break_init);
2451da177e4SLinus Torvalds 
2461da177e4SLinus Torvalds /*
2471da177e4SLinus Torvalds  * Read the word at offset "off" into the "struct user".  We
2481da177e4SLinus Torvalds  * actually access the pt_regs stored on the kernel stack.
2491da177e4SLinus Torvalds  */
ptrace_read_user(struct task_struct * tsk,unsigned long off,unsigned long __user * ret)2501da177e4SLinus Torvalds static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
2511da177e4SLinus Torvalds 			    unsigned long __user *ret)
2521da177e4SLinus Torvalds {
2531da177e4SLinus Torvalds 	unsigned long tmp;
2541da177e4SLinus Torvalds 
2555a4f5da5SWill Deacon 	if (off & 3)
2561da177e4SLinus Torvalds 		return -EIO;
2571da177e4SLinus Torvalds 
2581da177e4SLinus Torvalds 	tmp = 0;
25968b7f715SPaul Brook 	if (off == PT_TEXT_ADDR)
26068b7f715SPaul Brook 		tmp = tsk->mm->start_code;
26168b7f715SPaul Brook 	else if (off == PT_DATA_ADDR)
26268b7f715SPaul Brook 		tmp = tsk->mm->start_data;
26368b7f715SPaul Brook 	else if (off == PT_TEXT_END_ADDR)
26468b7f715SPaul Brook 		tmp = tsk->mm->end_code;
26568b7f715SPaul Brook 	else if (off < sizeof(struct pt_regs))
2661da177e4SLinus Torvalds 		tmp = get_user_reg(tsk, off >> 2);
2675a4f5da5SWill Deacon 	else if (off >= sizeof(struct user))
2685a4f5da5SWill Deacon 		return -EIO;
2691da177e4SLinus Torvalds 
2701da177e4SLinus Torvalds 	return put_user(tmp, ret);
2711da177e4SLinus Torvalds }
2721da177e4SLinus Torvalds 
2731da177e4SLinus Torvalds /*
2741da177e4SLinus Torvalds  * Write the word at offset "off" into "struct user".  We
2751da177e4SLinus Torvalds  * actually access the pt_regs stored on the kernel stack.
2761da177e4SLinus Torvalds  */
ptrace_write_user(struct task_struct * tsk,unsigned long off,unsigned long val)2771da177e4SLinus Torvalds static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
2781da177e4SLinus Torvalds 			     unsigned long val)
2791da177e4SLinus Torvalds {
2801da177e4SLinus Torvalds 	if (off & 3 || off >= sizeof(struct user))
2811da177e4SLinus Torvalds 		return -EIO;
2821da177e4SLinus Torvalds 
2831da177e4SLinus Torvalds 	if (off >= sizeof(struct pt_regs))
2841da177e4SLinus Torvalds 		return 0;
2851da177e4SLinus Torvalds 
2861da177e4SLinus Torvalds 	return put_user_reg(tsk, off >> 2, val);
2871da177e4SLinus Torvalds }
2881da177e4SLinus Torvalds 
2891da177e4SLinus Torvalds #ifdef CONFIG_IWMMXT
2901da177e4SLinus Torvalds 
2911da177e4SLinus Torvalds /*
2921da177e4SLinus Torvalds  * Get the child iWMMXt state.
2931da177e4SLinus Torvalds  */
ptrace_getwmmxregs(struct task_struct * tsk,void __user * ufp)2941da177e4SLinus Torvalds static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp)
2951da177e4SLinus Torvalds {
296e7c1b32fSAl Viro 	struct thread_info *thread = task_thread_info(tsk);
2971da177e4SLinus Torvalds 
2981da177e4SLinus Torvalds 	if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
2991da177e4SLinus Torvalds 		return -ENODATA;
3001da177e4SLinus Torvalds 	iwmmxt_task_disable(thread);  /* force it to ram */
301cdaabbd7SRussell King 	return copy_to_user(ufp, &thread->fpstate.iwmmxt, IWMMXT_SIZE)
302cdaabbd7SRussell King 		? -EFAULT : 0;
3031da177e4SLinus Torvalds }
3041da177e4SLinus Torvalds 
3051da177e4SLinus Torvalds /*
3061da177e4SLinus Torvalds  * Set the child iWMMXt state.
3071da177e4SLinus Torvalds  */
ptrace_setwmmxregs(struct task_struct * tsk,void __user * ufp)3081da177e4SLinus Torvalds static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)
3091da177e4SLinus Torvalds {
310e7c1b32fSAl Viro 	struct thread_info *thread = task_thread_info(tsk);
3111da177e4SLinus Torvalds 
3121da177e4SLinus Torvalds 	if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
3131da177e4SLinus Torvalds 		return -EACCES;
3141da177e4SLinus Torvalds 	iwmmxt_task_release(thread);  /* force a reload */
31517320a96SRussell King 	return copy_from_user(&thread->fpstate.iwmmxt, ufp, IWMMXT_SIZE)
316cdaabbd7SRussell King 		? -EFAULT : 0;
3171da177e4SLinus Torvalds }
3181da177e4SLinus Torvalds 
3191da177e4SLinus Torvalds #endif
3201da177e4SLinus Torvalds 
321864232faSWill Deacon #ifdef CONFIG_HAVE_HW_BREAKPOINT
322864232faSWill Deacon /*
323864232faSWill Deacon  * Convert a virtual register number into an index for a thread_info
324864232faSWill Deacon  * breakpoint array. Breakpoints are identified using positive numbers
325864232faSWill Deacon  * whilst watchpoints are negative. The registers are laid out as pairs
326864232faSWill Deacon  * of (address, control), each pair mapping to a unique hw_breakpoint struct.
327864232faSWill Deacon  * Register 0 is reserved for describing resource information.
328864232faSWill Deacon  */
ptrace_hbp_num_to_idx(long num)329864232faSWill Deacon static int ptrace_hbp_num_to_idx(long num)
330864232faSWill Deacon {
331864232faSWill Deacon 	if (num < 0)
332864232faSWill Deacon 		num = (ARM_MAX_BRP << 1) - num;
333864232faSWill Deacon 	return (num - 1) >> 1;
334864232faSWill Deacon }
335864232faSWill Deacon 
336864232faSWill Deacon /*
337864232faSWill Deacon  * Returns the virtual register number for the address of the
338864232faSWill Deacon  * breakpoint at index idx.
339864232faSWill Deacon  */
ptrace_hbp_idx_to_num(int idx)340864232faSWill Deacon static long ptrace_hbp_idx_to_num(int idx)
341864232faSWill Deacon {
342864232faSWill Deacon 	long mid = ARM_MAX_BRP << 1;
343864232faSWill Deacon 	long num = (idx << 1) + 1;
344864232faSWill Deacon 	return num > mid ? mid - num : num;
345864232faSWill Deacon }
346864232faSWill Deacon 
347864232faSWill Deacon /*
348864232faSWill Deacon  * Handle hitting a HW-breakpoint.
349864232faSWill Deacon  */
ptrace_hbptriggered(struct perf_event * bp,struct perf_sample_data * data,struct pt_regs * regs)350a8b0ca17SPeter Zijlstra static void ptrace_hbptriggered(struct perf_event *bp,
351864232faSWill Deacon 				     struct perf_sample_data *data,
352864232faSWill Deacon 				     struct pt_regs *regs)
353864232faSWill Deacon {
354864232faSWill Deacon 	struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
355864232faSWill Deacon 	long num;
356864232faSWill Deacon 	int i;
357864232faSWill Deacon 
358864232faSWill Deacon 	for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i)
359864232faSWill Deacon 		if (current->thread.debug.hbp[i] == bp)
360864232faSWill Deacon 			break;
361864232faSWill Deacon 
362864232faSWill Deacon 	num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i);
363864232faSWill Deacon 
364f71dd7dcSEric W. Biederman 	force_sig_ptrace_errno_trap((int)num, (void __user *)(bkpt->trigger));
365864232faSWill Deacon }
366864232faSWill Deacon 
367864232faSWill Deacon /*
368864232faSWill Deacon  * Set ptrace breakpoint pointers to zero for this task.
369864232faSWill Deacon  * This is required in order to prevent child processes from unregistering
370864232faSWill Deacon  * breakpoints held by their parent.
371864232faSWill Deacon  */
clear_ptrace_hw_breakpoint(struct task_struct * tsk)372864232faSWill Deacon void clear_ptrace_hw_breakpoint(struct task_struct *tsk)
373864232faSWill Deacon {
374864232faSWill Deacon 	memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp));
375864232faSWill Deacon }
376864232faSWill Deacon 
377864232faSWill Deacon /*
378864232faSWill Deacon  * Unregister breakpoints from this task and reset the pointers in
379864232faSWill Deacon  * the thread_struct.
380864232faSWill Deacon  */
flush_ptrace_hw_breakpoint(struct task_struct * tsk)381864232faSWill Deacon void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
382864232faSWill Deacon {
383864232faSWill Deacon 	int i;
384864232faSWill Deacon 	struct thread_struct *t = &tsk->thread;
385864232faSWill Deacon 
386864232faSWill Deacon 	for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) {
387864232faSWill Deacon 		if (t->debug.hbp[i]) {
388864232faSWill Deacon 			unregister_hw_breakpoint(t->debug.hbp[i]);
389864232faSWill Deacon 			t->debug.hbp[i] = NULL;
390864232faSWill Deacon 		}
391864232faSWill Deacon 	}
392864232faSWill Deacon }
393864232faSWill Deacon 
ptrace_get_hbp_resource_info(void)394864232faSWill Deacon static u32 ptrace_get_hbp_resource_info(void)
395864232faSWill Deacon {
396864232faSWill Deacon 	u8 num_brps, num_wrps, debug_arch, wp_len;
397864232faSWill Deacon 	u32 reg = 0;
398864232faSWill Deacon 
399864232faSWill Deacon 	num_brps	= hw_breakpoint_slots(TYPE_INST);
400864232faSWill Deacon 	num_wrps	= hw_breakpoint_slots(TYPE_DATA);
401864232faSWill Deacon 	debug_arch	= arch_get_debug_arch();
402864232faSWill Deacon 	wp_len		= arch_get_max_wp_len();
403864232faSWill Deacon 
404864232faSWill Deacon 	reg		|= debug_arch;
405864232faSWill Deacon 	reg		<<= 8;
406864232faSWill Deacon 	reg		|= wp_len;
407864232faSWill Deacon 	reg		<<= 8;
408864232faSWill Deacon 	reg		|= num_wrps;
409864232faSWill Deacon 	reg		<<= 8;
410864232faSWill Deacon 	reg		|= num_brps;
411864232faSWill Deacon 
412864232faSWill Deacon 	return reg;
413864232faSWill Deacon }
414864232faSWill Deacon 
ptrace_hbp_create(struct task_struct * tsk,int type)415864232faSWill Deacon static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
416864232faSWill Deacon {
417864232faSWill Deacon 	struct perf_event_attr attr;
418864232faSWill Deacon 
419864232faSWill Deacon 	ptrace_breakpoint_init(&attr);
420864232faSWill Deacon 
421864232faSWill Deacon 	/* Initialise fields to sane defaults. */
422864232faSWill Deacon 	attr.bp_addr	= 0;
423864232faSWill Deacon 	attr.bp_len	= HW_BREAKPOINT_LEN_4;
424864232faSWill Deacon 	attr.bp_type	= type;
425864232faSWill Deacon 	attr.disabled	= 1;
426864232faSWill Deacon 
4274dc0da86SAvi Kivity 	return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL,
4284dc0da86SAvi Kivity 					   tsk);
429864232faSWill Deacon }
430864232faSWill Deacon 
ptrace_gethbpregs(struct task_struct * tsk,long num,unsigned long __user * data)431864232faSWill Deacon static int ptrace_gethbpregs(struct task_struct *tsk, long num,
432864232faSWill Deacon 			     unsigned long  __user *data)
433864232faSWill Deacon {
434864232faSWill Deacon 	u32 reg;
435864232faSWill Deacon 	int idx, ret = 0;
436864232faSWill Deacon 	struct perf_event *bp;
437864232faSWill Deacon 	struct arch_hw_breakpoint_ctrl arch_ctrl;
438864232faSWill Deacon 
439864232faSWill Deacon 	if (num == 0) {
440864232faSWill Deacon 		reg = ptrace_get_hbp_resource_info();
441864232faSWill Deacon 	} else {
442864232faSWill Deacon 		idx = ptrace_hbp_num_to_idx(num);
443864232faSWill Deacon 		if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
444864232faSWill Deacon 			ret = -EINVAL;
445864232faSWill Deacon 			goto out;
446864232faSWill Deacon 		}
447864232faSWill Deacon 
448864232faSWill Deacon 		bp = tsk->thread.debug.hbp[idx];
449864232faSWill Deacon 		if (!bp) {
450864232faSWill Deacon 			reg = 0;
451864232faSWill Deacon 			goto put;
452864232faSWill Deacon 		}
453864232faSWill Deacon 
454864232faSWill Deacon 		arch_ctrl = counter_arch_bp(bp)->ctrl;
455864232faSWill Deacon 
456864232faSWill Deacon 		/*
457864232faSWill Deacon 		 * Fix up the len because we may have adjusted it
458864232faSWill Deacon 		 * to compensate for an unaligned address.
459864232faSWill Deacon 		 */
460864232faSWill Deacon 		while (!(arch_ctrl.len & 0x1))
461864232faSWill Deacon 			arch_ctrl.len >>= 1;
462864232faSWill Deacon 
463ba55d3dbSWill Deacon 		if (num & 0x1)
464864232faSWill Deacon 			reg = bp->attr.bp_addr;
465ba55d3dbSWill Deacon 		else
466ba55d3dbSWill Deacon 			reg = encode_ctrl_reg(arch_ctrl);
467864232faSWill Deacon 	}
468864232faSWill Deacon 
469864232faSWill Deacon put:
470864232faSWill Deacon 	if (put_user(reg, data))
471864232faSWill Deacon 		ret = -EFAULT;
472864232faSWill Deacon 
473864232faSWill Deacon out:
474864232faSWill Deacon 	return ret;
475864232faSWill Deacon }
476864232faSWill Deacon 
ptrace_sethbpregs(struct task_struct * tsk,long num,unsigned long __user * data)477864232faSWill Deacon static int ptrace_sethbpregs(struct task_struct *tsk, long num,
478864232faSWill Deacon 			     unsigned long __user *data)
479864232faSWill Deacon {
480864232faSWill Deacon 	int idx, gen_len, gen_type, implied_type, ret = 0;
481864232faSWill Deacon 	u32 user_val;
482864232faSWill Deacon 	struct perf_event *bp;
483864232faSWill Deacon 	struct arch_hw_breakpoint_ctrl ctrl;
484864232faSWill Deacon 	struct perf_event_attr attr;
485864232faSWill Deacon 
486864232faSWill Deacon 	if (num == 0)
487864232faSWill Deacon 		goto out;
488864232faSWill Deacon 	else if (num < 0)
489864232faSWill Deacon 		implied_type = HW_BREAKPOINT_RW;
490864232faSWill Deacon 	else
491864232faSWill Deacon 		implied_type = HW_BREAKPOINT_X;
492864232faSWill Deacon 
493864232faSWill Deacon 	idx = ptrace_hbp_num_to_idx(num);
494864232faSWill Deacon 	if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
495864232faSWill Deacon 		ret = -EINVAL;
496864232faSWill Deacon 		goto out;
497864232faSWill Deacon 	}
498864232faSWill Deacon 
499864232faSWill Deacon 	if (get_user(user_val, data)) {
500864232faSWill Deacon 		ret = -EFAULT;
501864232faSWill Deacon 		goto out;
502864232faSWill Deacon 	}
503864232faSWill Deacon 
504864232faSWill Deacon 	bp = tsk->thread.debug.hbp[idx];
505864232faSWill Deacon 	if (!bp) {
506864232faSWill Deacon 		bp = ptrace_hbp_create(tsk, implied_type);
507864232faSWill Deacon 		if (IS_ERR(bp)) {
508864232faSWill Deacon 			ret = PTR_ERR(bp);
509864232faSWill Deacon 			goto out;
510864232faSWill Deacon 		}
511864232faSWill Deacon 		tsk->thread.debug.hbp[idx] = bp;
512864232faSWill Deacon 	}
513864232faSWill Deacon 
514864232faSWill Deacon 	attr = bp->attr;
515864232faSWill Deacon 
516864232faSWill Deacon 	if (num & 0x1) {
517864232faSWill Deacon 		/* Address */
518864232faSWill Deacon 		attr.bp_addr	= user_val;
519864232faSWill Deacon 	} else {
520864232faSWill Deacon 		/* Control */
521864232faSWill Deacon 		decode_ctrl_reg(user_val, &ctrl);
522864232faSWill Deacon 		ret = arch_bp_generic_fields(ctrl, &gen_len, &gen_type);
523864232faSWill Deacon 		if (ret)
524864232faSWill Deacon 			goto out;
525864232faSWill Deacon 
526864232faSWill Deacon 		if ((gen_type & implied_type) != gen_type) {
527864232faSWill Deacon 			ret = -EINVAL;
528864232faSWill Deacon 			goto out;
529864232faSWill Deacon 		}
530864232faSWill Deacon 
531864232faSWill Deacon 		attr.bp_len	= gen_len;
532864232faSWill Deacon 		attr.bp_type	= gen_type;
533864232faSWill Deacon 		attr.disabled	= !ctrl.enabled;
534864232faSWill Deacon 	}
535864232faSWill Deacon 
536864232faSWill Deacon 	ret = modify_user_hw_breakpoint(bp, &attr);
537864232faSWill Deacon out:
538864232faSWill Deacon 	return ret;
539864232faSWill Deacon }
540864232faSWill Deacon #endif
541864232faSWill Deacon 
5425be6f62bSDave Martin /* regset get/set implementations */
5435be6f62bSDave Martin 
gpr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)5445be6f62bSDave Martin static int gpr_get(struct task_struct *target,
5455be6f62bSDave Martin 		   const struct user_regset *regset,
5463598e9f0SAl Viro 		   struct membuf to)
5475be6f62bSDave Martin {
5483598e9f0SAl Viro 	return membuf_write(&to, task_pt_regs(target), sizeof(struct pt_regs));
5495be6f62bSDave Martin }
5505be6f62bSDave Martin 
gpr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)5515be6f62bSDave Martin static int gpr_set(struct task_struct *target,
5525be6f62bSDave Martin 		   const struct user_regset *regset,
5535be6f62bSDave Martin 		   unsigned int pos, unsigned int count,
5545be6f62bSDave Martin 		   const void *kbuf, const void __user *ubuf)
5555be6f62bSDave Martin {
5565be6f62bSDave Martin 	int ret;
557228dbbfbSDave Martin 	struct pt_regs newregs = *task_pt_regs(target);
5585be6f62bSDave Martin 
5595be6f62bSDave Martin 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
5605be6f62bSDave Martin 				 &newregs,
5615be6f62bSDave Martin 				 0, sizeof(newregs));
5625be6f62bSDave Martin 	if (ret)
5635be6f62bSDave Martin 		return ret;
5645be6f62bSDave Martin 
5655be6f62bSDave Martin 	if (!valid_user_regs(&newregs))
5665be6f62bSDave Martin 		return -EINVAL;
5675be6f62bSDave Martin 
5685be6f62bSDave Martin 	*task_pt_regs(target) = newregs;
5695be6f62bSDave Martin 	return 0;
5705be6f62bSDave Martin }
5715be6f62bSDave Martin 
fpa_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)5725be6f62bSDave Martin static int fpa_get(struct task_struct *target,
5735be6f62bSDave Martin 		   const struct user_regset *regset,
5743598e9f0SAl Viro 		   struct membuf to)
5755be6f62bSDave Martin {
5763598e9f0SAl Viro 	return membuf_write(&to, &task_thread_info(target)->fpstate,
5773598e9f0SAl Viro 				 sizeof(struct user_fp));
5785be6f62bSDave Martin }
5795be6f62bSDave Martin 
fpa_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)5805be6f62bSDave Martin static int fpa_set(struct task_struct *target,
5815be6f62bSDave Martin 		   const struct user_regset *regset,
5825be6f62bSDave Martin 		   unsigned int pos, unsigned int count,
5835be6f62bSDave Martin 		   const void *kbuf, const void __user *ubuf)
5845be6f62bSDave Martin {
5855be6f62bSDave Martin 	struct thread_info *thread = task_thread_info(target);
5865be6f62bSDave Martin 
5875be6f62bSDave Martin 	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
5885be6f62bSDave Martin 		&thread->fpstate,
5895be6f62bSDave Martin 		0, sizeof(struct user_fp));
5905be6f62bSDave Martin }
5915be6f62bSDave Martin 
5925be6f62bSDave Martin #ifdef CONFIG_VFP
5935be6f62bSDave Martin /*
5945be6f62bSDave Martin  * VFP register get/set implementations.
5955be6f62bSDave Martin  *
5965be6f62bSDave Martin  * With respect to the kernel, struct user_fp is divided into three chunks:
5975be6f62bSDave Martin  * 16 or 32 real VFP registers (d0-d15 or d0-31)
5985be6f62bSDave Martin  *	These are transferred to/from the real registers in the task's
5995be6f62bSDave Martin  *	vfp_hard_struct.  The number of registers depends on the kernel
6005be6f62bSDave Martin  *	configuration.
6015be6f62bSDave Martin  *
6025be6f62bSDave Martin  * 16 or 0 fake VFP registers (d16-d31 or empty)
6035be6f62bSDave Martin  *	i.e., the user_vfp structure has space for 32 registers even if
6045be6f62bSDave Martin  *	the kernel doesn't have them all.
6055be6f62bSDave Martin  *
6065be6f62bSDave Martin  *	vfp_get() reads this chunk as zero where applicable
6075be6f62bSDave Martin  *	vfp_set() ignores this chunk
6085be6f62bSDave Martin  *
6095be6f62bSDave Martin  * 1 word for the FPSCR
6105be6f62bSDave Martin  */
vfp_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)6115be6f62bSDave Martin static int vfp_get(struct task_struct *target,
6125be6f62bSDave Martin 		   const struct user_regset *regset,
6133598e9f0SAl Viro 		   struct membuf to)
6145be6f62bSDave Martin {
6155be6f62bSDave Martin 	struct thread_info *thread = task_thread_info(target);
6165be6f62bSDave Martin 	struct vfp_hard_struct const *vfp = &thread->vfpstate.hard;
6175be6f62bSDave Martin 	const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
6185be6f62bSDave Martin 
6195be6f62bSDave Martin 	vfp_sync_hwstate(thread);
6205be6f62bSDave Martin 
6213598e9f0SAl Viro 	membuf_write(&to, vfp->fpregs, sizeof(vfp->fpregs));
6223598e9f0SAl Viro 	membuf_zero(&to, user_fpscr_offset - sizeof(vfp->fpregs));
6233598e9f0SAl Viro 	return membuf_store(&to, vfp->fpscr);
6245be6f62bSDave Martin }
6255be6f62bSDave Martin 
6265be6f62bSDave Martin /*
6275be6f62bSDave Martin  * For vfp_set() a read-modify-write is done on the VFP registers,
6285be6f62bSDave Martin  * in order to avoid writing back a half-modified set of registers on
6295be6f62bSDave Martin  * failure.
6305be6f62bSDave Martin  */
vfp_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)6315be6f62bSDave Martin static int vfp_set(struct task_struct *target,
6325be6f62bSDave Martin 			  const struct user_regset *regset,
6335be6f62bSDave Martin 			  unsigned int pos, unsigned int count,
6345be6f62bSDave Martin 			  const void *kbuf, const void __user *ubuf)
6355be6f62bSDave Martin {
6365be6f62bSDave Martin 	int ret;
6375be6f62bSDave Martin 	struct thread_info *thread = task_thread_info(target);
638247f4993SDave Martin 	struct vfp_hard_struct new_vfp;
6395be6f62bSDave Martin 	const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
6405be6f62bSDave Martin 	const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
6415be6f62bSDave Martin 
642247f4993SDave Martin 	vfp_sync_hwstate(thread);
643247f4993SDave Martin 	new_vfp = thread->vfpstate.hard;
644247f4993SDave Martin 
6455be6f62bSDave Martin 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
6465be6f62bSDave Martin 				  &new_vfp.fpregs,
6475be6f62bSDave Martin 				  user_fpregs_offset,
6485be6f62bSDave Martin 				  user_fpregs_offset + sizeof(new_vfp.fpregs));
6495be6f62bSDave Martin 	if (ret)
6505be6f62bSDave Martin 		return ret;
6515be6f62bSDave Martin 
652dd127cf2SSergey Shtylyov 	user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
6535be6f62bSDave Martin 				  user_fpregs_offset + sizeof(new_vfp.fpregs),
6545be6f62bSDave Martin 				  user_fpscr_offset);
6555be6f62bSDave Martin 
6565be6f62bSDave Martin 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
6575be6f62bSDave Martin 				 &new_vfp.fpscr,
6585be6f62bSDave Martin 				 user_fpscr_offset,
6595be6f62bSDave Martin 				 user_fpscr_offset + sizeof(new_vfp.fpscr));
6605be6f62bSDave Martin 	if (ret)
6615be6f62bSDave Martin 		return ret;
6625be6f62bSDave Martin 
6638130b9d7SWill Deacon 	thread->vfpstate.hard = new_vfp;
664e2dfb4b8SRussell King 	vfp_flush_hwstate(thread);
6655be6f62bSDave Martin 
6665be6f62bSDave Martin 	return 0;
6675be6f62bSDave Martin }
6685be6f62bSDave Martin #endif /* CONFIG_VFP */
6695be6f62bSDave Martin 
6705be6f62bSDave Martin enum arm_regset {
6715be6f62bSDave Martin 	REGSET_GPR,
6725be6f62bSDave Martin 	REGSET_FPR,
6735be6f62bSDave Martin #ifdef CONFIG_VFP
6745be6f62bSDave Martin 	REGSET_VFP,
6755be6f62bSDave Martin #endif
6765be6f62bSDave Martin };
6775be6f62bSDave Martin 
6785be6f62bSDave Martin static const struct user_regset arm_regsets[] = {
6795be6f62bSDave Martin 	[REGSET_GPR] = {
6805be6f62bSDave Martin 		.core_note_type = NT_PRSTATUS,
6815be6f62bSDave Martin 		.n = ELF_NGREG,
6825be6f62bSDave Martin 		.size = sizeof(u32),
6835be6f62bSDave Martin 		.align = sizeof(u32),
6843598e9f0SAl Viro 		.regset_get = gpr_get,
6855be6f62bSDave Martin 		.set = gpr_set
6865be6f62bSDave Martin 	},
6875be6f62bSDave Martin 	[REGSET_FPR] = {
6885be6f62bSDave Martin 		/*
6895be6f62bSDave Martin 		 * For the FPA regs in fpstate, the real fields are a mixture
6905be6f62bSDave Martin 		 * of sizes, so pretend that the registers are word-sized:
6915be6f62bSDave Martin 		 */
6925be6f62bSDave Martin 		.core_note_type = NT_PRFPREG,
6935be6f62bSDave Martin 		.n = sizeof(struct user_fp) / sizeof(u32),
6945be6f62bSDave Martin 		.size = sizeof(u32),
6955be6f62bSDave Martin 		.align = sizeof(u32),
6963598e9f0SAl Viro 		.regset_get = fpa_get,
6975be6f62bSDave Martin 		.set = fpa_set
6985be6f62bSDave Martin 	},
6995be6f62bSDave Martin #ifdef CONFIG_VFP
7005be6f62bSDave Martin 	[REGSET_VFP] = {
7015be6f62bSDave Martin 		/*
7025be6f62bSDave Martin 		 * Pretend that the VFP regs are word-sized, since the FPSCR is
7035be6f62bSDave Martin 		 * a single word dangling at the end of struct user_vfp:
7045be6f62bSDave Martin 		 */
7055be6f62bSDave Martin 		.core_note_type = NT_ARM_VFP,
7065be6f62bSDave Martin 		.n = ARM_VFPREGS_SIZE / sizeof(u32),
7075be6f62bSDave Martin 		.size = sizeof(u32),
7085be6f62bSDave Martin 		.align = sizeof(u32),
7093598e9f0SAl Viro 		.regset_get = vfp_get,
7105be6f62bSDave Martin 		.set = vfp_set
7115be6f62bSDave Martin 	},
7125be6f62bSDave Martin #endif /* CONFIG_VFP */
7135be6f62bSDave Martin };
7145be6f62bSDave Martin 
7155be6f62bSDave Martin static const struct user_regset_view user_arm_view = {
7165be6f62bSDave Martin 	.name = "arm", .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI,
7175be6f62bSDave Martin 	.regsets = arm_regsets, .n = ARRAY_SIZE(arm_regsets)
7185be6f62bSDave Martin };
7195be6f62bSDave Martin 
task_user_regset_view(struct task_struct * task)7205be6f62bSDave Martin const struct user_regset_view *task_user_regset_view(struct task_struct *task)
7215be6f62bSDave Martin {
7225be6f62bSDave Martin 	return &user_arm_view;
7235be6f62bSDave Martin }
7245be6f62bSDave Martin 
arch_ptrace(struct task_struct * child,long request,unsigned long addr,unsigned long data)7259b05a69eSNamhyung Kim long arch_ptrace(struct task_struct *child, long request,
7269b05a69eSNamhyung Kim 		 unsigned long addr, unsigned long data)
7271da177e4SLinus Torvalds {
7281da177e4SLinus Torvalds 	int ret;
729b640a0d1SNamhyung Kim 	unsigned long __user *datap = (unsigned long __user *) data;
7301da177e4SLinus Torvalds 
7311da177e4SLinus Torvalds 	switch (request) {
7321da177e4SLinus Torvalds 		case PTRACE_PEEKUSR:
733b640a0d1SNamhyung Kim 			ret = ptrace_read_user(child, addr, datap);
7341da177e4SLinus Torvalds 			break;
7351da177e4SLinus Torvalds 
7361da177e4SLinus Torvalds 		case PTRACE_POKEUSR:
7371da177e4SLinus Torvalds 			ret = ptrace_write_user(child, addr, data);
7381da177e4SLinus Torvalds 			break;
7391da177e4SLinus Torvalds 
7401da177e4SLinus Torvalds 		case PTRACE_GETREGS:
7415be6f62bSDave Martin 			ret = copy_regset_to_user(child,
7425be6f62bSDave Martin 						  &user_arm_view, REGSET_GPR,
7435be6f62bSDave Martin 						  0, sizeof(struct pt_regs),
7445be6f62bSDave Martin 						  datap);
7451da177e4SLinus Torvalds 			break;
7461da177e4SLinus Torvalds 
7471da177e4SLinus Torvalds 		case PTRACE_SETREGS:
7485be6f62bSDave Martin 			ret = copy_regset_from_user(child,
7495be6f62bSDave Martin 						    &user_arm_view, REGSET_GPR,
7505be6f62bSDave Martin 						    0, sizeof(struct pt_regs),
7515be6f62bSDave Martin 						    datap);
7521da177e4SLinus Torvalds 			break;
7531da177e4SLinus Torvalds 
7541da177e4SLinus Torvalds 		case PTRACE_GETFPREGS:
7555be6f62bSDave Martin 			ret = copy_regset_to_user(child,
7565be6f62bSDave Martin 						  &user_arm_view, REGSET_FPR,
7575be6f62bSDave Martin 						  0, sizeof(union fp_state),
7585be6f62bSDave Martin 						  datap);
7591da177e4SLinus Torvalds 			break;
7601da177e4SLinus Torvalds 
7611da177e4SLinus Torvalds 		case PTRACE_SETFPREGS:
7625be6f62bSDave Martin 			ret = copy_regset_from_user(child,
7635be6f62bSDave Martin 						    &user_arm_view, REGSET_FPR,
7645be6f62bSDave Martin 						    0, sizeof(union fp_state),
7655be6f62bSDave Martin 						    datap);
7661da177e4SLinus Torvalds 			break;
7671da177e4SLinus Torvalds 
7681da177e4SLinus Torvalds #ifdef CONFIG_IWMMXT
7691da177e4SLinus Torvalds 		case PTRACE_GETWMMXREGS:
770b640a0d1SNamhyung Kim 			ret = ptrace_getwmmxregs(child, datap);
7711da177e4SLinus Torvalds 			break;
7721da177e4SLinus Torvalds 
7731da177e4SLinus Torvalds 		case PTRACE_SETWMMXREGS:
774b640a0d1SNamhyung Kim 			ret = ptrace_setwmmxregs(child, datap);
7751da177e4SLinus Torvalds 			break;
7761da177e4SLinus Torvalds #endif
7771da177e4SLinus Torvalds 
7781da177e4SLinus Torvalds 		case PTRACE_GET_THREAD_AREA:
779a4780adeSAndré Hentschel 			ret = put_user(task_thread_info(child)->tp_value[0],
780b640a0d1SNamhyung Kim 				       datap);
7811da177e4SLinus Torvalds 			break;
7821da177e4SLinus Torvalds 
7833f471126SNicolas Pitre 		case PTRACE_SET_SYSCALL:
784*4697b584SKees Cook 			if (data != -1)
785*4697b584SKees Cook 				data &= __NR_SYSCALL_MASK;
786*4697b584SKees Cook 			task_thread_info(child)->abi_syscall = data;
7873f471126SNicolas Pitre 			ret = 0;
7883f471126SNicolas Pitre 			break;
7893f471126SNicolas Pitre 
7903d1228eaSCatalin Marinas #ifdef CONFIG_VFP
7913d1228eaSCatalin Marinas 		case PTRACE_GETVFPREGS:
7925be6f62bSDave Martin 			ret = copy_regset_to_user(child,
7935be6f62bSDave Martin 						  &user_arm_view, REGSET_VFP,
7945be6f62bSDave Martin 						  0, ARM_VFPREGS_SIZE,
7955be6f62bSDave Martin 						  datap);
7963d1228eaSCatalin Marinas 			break;
7973d1228eaSCatalin Marinas 
7983d1228eaSCatalin Marinas 		case PTRACE_SETVFPREGS:
7995be6f62bSDave Martin 			ret = copy_regset_from_user(child,
8005be6f62bSDave Martin 						    &user_arm_view, REGSET_VFP,
8015be6f62bSDave Martin 						    0, ARM_VFPREGS_SIZE,
8025be6f62bSDave Martin 						    datap);
8033d1228eaSCatalin Marinas 			break;
8043d1228eaSCatalin Marinas #endif
8053d1228eaSCatalin Marinas 
806864232faSWill Deacon #ifdef CONFIG_HAVE_HW_BREAKPOINT
807864232faSWill Deacon 		case PTRACE_GETHBPREGS:
808864232faSWill Deacon 			ret = ptrace_gethbpregs(child, addr,
809864232faSWill Deacon 						(unsigned long __user *)data);
810864232faSWill Deacon 			break;
811864232faSWill Deacon 		case PTRACE_SETHBPREGS:
812864232faSWill Deacon 			ret = ptrace_sethbpregs(child, addr,
813864232faSWill Deacon 						(unsigned long __user *)data);
814864232faSWill Deacon 			break;
815864232faSWill Deacon #endif
816864232faSWill Deacon 
8171da177e4SLinus Torvalds 		default:
8181da177e4SLinus Torvalds 			ret = ptrace_request(child, request, addr, data);
8191da177e4SLinus Torvalds 			break;
8201da177e4SLinus Torvalds 	}
8211da177e4SLinus Torvalds 
8221da177e4SLinus Torvalds 	return ret;
8231da177e4SLinus Torvalds }
8241da177e4SLinus Torvalds 
825ad722541SWill Deacon enum ptrace_syscall_dir {
826ad722541SWill Deacon 	PTRACE_SYSCALL_ENTER = 0,
827ad722541SWill Deacon 	PTRACE_SYSCALL_EXIT,
828ad722541SWill Deacon };
829ad722541SWill Deacon 
report_syscall(struct pt_regs * regs,enum ptrace_syscall_dir dir)83042da6b7eSEric W. Biederman static void report_syscall(struct pt_regs *regs, enum ptrace_syscall_dir dir)
8311da177e4SLinus Torvalds {
8321da177e4SLinus Torvalds 	unsigned long ip;
8331da177e4SLinus Torvalds 
8346a68b6f5SWill Deacon 	/*
8356a68b6f5SWill Deacon 	 * IP is used to denote syscall entry/exit:
8366a68b6f5SWill Deacon 	 * IP = 0 -> entry, =1 -> exit
8376a68b6f5SWill Deacon 	 */
8386a68b6f5SWill Deacon 	ip = regs->ARM_ip;
839ad722541SWill Deacon 	regs->ARM_ip = dir;
8406a68b6f5SWill Deacon 
841ad722541SWill Deacon 	if (dir == PTRACE_SYSCALL_EXIT)
842153474baSEric W. Biederman 		ptrace_report_syscall_exit(regs, 0);
843153474baSEric W. Biederman 	else if (ptrace_report_syscall_entry(regs))
8444e57a4ddSArnd Bergmann 		current_thread_info()->abi_syscall = -1;
8450693bf68SWade Farnsworth 
8461da177e4SLinus Torvalds 	regs->ARM_ip = ip;
847ad722541SWill Deacon }
8483f471126SNicolas Pitre 
syscall_trace_enter(struct pt_regs * regs)8494e57a4ddSArnd Bergmann asmlinkage int syscall_trace_enter(struct pt_regs *regs)
850ad722541SWill Deacon {
8514e57a4ddSArnd Bergmann 	int scno;
8529b790d71SKees Cook 
8530f3912fdSKees Cook 	if (test_thread_flag(TIF_SYSCALL_TRACE))
85442da6b7eSEric W. Biederman 		report_syscall(regs, PTRACE_SYSCALL_ENTER);
8550f3912fdSKees Cook 
8560f3912fdSKees Cook 	/* Do seccomp after ptrace; syscall may have changed. */
857a4412fc9SAndy Lutomirski #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER
858fefad9efSChristian Brauner 	if (secure_computing() == -1)
8599b790d71SKees Cook 		return -1;
860a4412fc9SAndy Lutomirski #else
861a4412fc9SAndy Lutomirski 	/* XXX: remove this once OABI gets fixed */
8624e57a4ddSArnd Bergmann 	secure_computing_strict(syscall_get_nr(current, regs));
863a4412fc9SAndy Lutomirski #endif
8649b790d71SKees Cook 
8650f3912fdSKees Cook 	/* Tracer or seccomp may have changed syscall. */
8664e57a4ddSArnd Bergmann 	scno = syscall_get_nr(current, regs);
8679b790d71SKees Cook 
8681f66e06fSWade Farnsworth 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
869ebb5e15cSWill Deacon 		trace_sys_enter(regs, scno);
8709b790d71SKees Cook 
87191397401SEric Paris 	audit_syscall_entry(scno, regs->ARM_r0, regs->ARM_r1, regs->ARM_r2,
87291397401SEric Paris 			    regs->ARM_r3);
8739b790d71SKees Cook 
874ebb5e15cSWill Deacon 	return scno;
875ad722541SWill Deacon }
876ad722541SWill Deacon 
syscall_trace_exit(struct pt_regs * regs)877b10bca0bSWill Deacon asmlinkage void syscall_trace_exit(struct pt_regs *regs)
878ad722541SWill Deacon {
879b10bca0bSWill Deacon 	/*
880b10bca0bSWill Deacon 	 * Audit the syscall before anything else, as a debugger may
881b10bca0bSWill Deacon 	 * come in and change the current registers.
882b10bca0bSWill Deacon 	 */
8835125430cSWill Deacon 	audit_syscall_exit(regs);
8849b790d71SKees Cook 
885b10bca0bSWill Deacon 	/*
886b10bca0bSWill Deacon 	 * Note that we haven't updated the ->syscall field for the
887b10bca0bSWill Deacon 	 * current thread. This isn't a problem because it will have
888b10bca0bSWill Deacon 	 * been set on syscall entry and there hasn't been an opportunity
889b10bca0bSWill Deacon 	 * for a PTRACE_SET_SYSCALL since then.
890b10bca0bSWill Deacon 	 */
891b10bca0bSWill Deacon 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
892b10bca0bSWill Deacon 		trace_sys_exit(regs, regs_return_value(regs));
893b10bca0bSWill Deacon 
894b10bca0bSWill Deacon 	if (test_thread_flag(TIF_SYSCALL_TRACE))
89542da6b7eSEric W. Biederman 		report_syscall(regs, PTRACE_SYSCALL_EXIT);
8961da177e4SLinus Torvalds }
897