xref: /openbmc/linux/arch/mips/include/asm/ptrace.h (revision f91955da)
1384740dcSRalf Baechle /*
2384740dcSRalf Baechle  * This file is subject to the terms and conditions of the GNU General Public
3384740dcSRalf Baechle  * License.  See the file "COPYING" in the main directory of this archive
4384740dcSRalf Baechle  * for more details.
5384740dcSRalf Baechle  *
6384740dcSRalf Baechle  * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 by Ralf Baechle
7384740dcSRalf Baechle  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8384740dcSRalf Baechle  */
9384740dcSRalf Baechle #ifndef _ASM_PTRACE_H
10384740dcSRalf Baechle #define _ASM_PTRACE_H
11384740dcSRalf Baechle 
12384740dcSRalf Baechle 
130926bf95SDavid Daney #include <linux/compiler.h>
14384740dcSRalf Baechle #include <linux/linkage.h>
15f6a3176aSYoichi Yuasa #include <linux/types.h>
16384740dcSRalf Baechle #include <asm/isadep.h>
1740e084a5SRalf Baechle #include <asm/page.h>
1840e084a5SRalf Baechle #include <asm/thread_info.h>
1961730c53SDavid Howells #include <uapi/asm/ptrace.h>
20384740dcSRalf Baechle 
218f657933SDavid Daney /*
228f657933SDavid Daney  * This struct defines the way the registers are stored on the stack during a
238f657933SDavid Daney  * system call/exception. As usual the registers k0/k1 aren't being saved.
2440e084a5SRalf Baechle  *
2540e084a5SRalf Baechle  * If you add a register here, also add it to regoffset_table[] in
2640e084a5SRalf Baechle  * arch/mips/kernel/ptrace.c.
278f657933SDavid Daney  */
288f657933SDavid Daney struct pt_regs {
298f657933SDavid Daney #ifdef CONFIG_32BIT
308f657933SDavid Daney 	/* Pad bytes for argument save space on the stack. */
31e90e6fddSAlex Smith 	unsigned long pad0[8];
328f657933SDavid Daney #endif
338f657933SDavid Daney 
348f657933SDavid Daney 	/* Saved main processor registers. */
358f657933SDavid Daney 	unsigned long regs[32];
368f657933SDavid Daney 
378f657933SDavid Daney 	/* Saved special registers. */
388f657933SDavid Daney 	unsigned long cp0_status;
398f657933SDavid Daney 	unsigned long hi;
408f657933SDavid Daney 	unsigned long lo;
418f657933SDavid Daney #ifdef CONFIG_CPU_HAS_SMARTMIPS
428f657933SDavid Daney 	unsigned long acx;
438f657933SDavid Daney #endif
448f657933SDavid Daney 	unsigned long cp0_badvaddr;
458f657933SDavid Daney 	unsigned long cp0_cause;
468f657933SDavid Daney 	unsigned long cp0_epc;
478f657933SDavid Daney #ifdef CONFIG_CPU_CAVIUM_OCTEON
48ac655fb7SDavid Daney 	unsigned long long mpl[6];        /* MTM{0-5} */
49ac655fb7SDavid Daney 	unsigned long long mtp[6];        /* MTP{0-5} */
508f657933SDavid Daney #endif
5140e084a5SRalf Baechle 	unsigned long __last[0];
528f657933SDavid Daney } __aligned(8);
538f657933SDavid Daney 
kernel_stack_pointer(struct pt_regs * regs)5440e084a5SRalf Baechle static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
5540e084a5SRalf Baechle {
56a78ddac1SHuang Pei 	return regs->regs[29];
5740e084a5SRalf Baechle }
5840e084a5SRalf Baechle 
instruction_pointer_set(struct pt_regs * regs,unsigned long val)5940e084a5SRalf Baechle static inline void instruction_pointer_set(struct pt_regs *regs,
6040e084a5SRalf Baechle                                            unsigned long val)
6140e084a5SRalf Baechle {
6240e084a5SRalf Baechle 	regs->cp0_epc = val;
63ab63a809SJiaxun Yang 	regs->cp0_cause &= ~CAUSEF_BD;
6440e084a5SRalf Baechle }
6540e084a5SRalf Baechle 
6640e084a5SRalf Baechle /* Query offset/name of register from its name/offset */
6740e084a5SRalf Baechle extern int regs_query_register_offset(const char *name);
6840e084a5SRalf Baechle #define MAX_REG_OFFSET (offsetof(struct pt_regs, __last))
6940e084a5SRalf Baechle 
7040e084a5SRalf Baechle /**
7140e084a5SRalf Baechle  * regs_get_register() - get register value from its offset
7240e084a5SRalf Baechle  * @regs:       pt_regs from which register value is gotten.
7340e084a5SRalf Baechle  * @offset:     offset number of the register.
7440e084a5SRalf Baechle  *
7540e084a5SRalf Baechle  * regs_get_register returns the value of a register. The @offset is the
7640e084a5SRalf Baechle  * offset of the register in struct pt_regs address which specified by @regs.
7740e084a5SRalf Baechle  * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
7840e084a5SRalf Baechle  */
regs_get_register(struct pt_regs * regs,unsigned int offset)7940e084a5SRalf Baechle static inline unsigned long regs_get_register(struct pt_regs *regs,
8040e084a5SRalf Baechle                                               unsigned int offset)
8140e084a5SRalf Baechle {
8240e084a5SRalf Baechle 	if (unlikely(offset > MAX_REG_OFFSET))
8340e084a5SRalf Baechle 		return 0;
8440e084a5SRalf Baechle 
8540e084a5SRalf Baechle 	return *(unsigned long *)((unsigned long)regs + offset);
8640e084a5SRalf Baechle }
8740e084a5SRalf Baechle 
8840e084a5SRalf Baechle /**
8940e084a5SRalf Baechle  * regs_within_kernel_stack() - check the address in the stack
9040e084a5SRalf Baechle  * @regs:       pt_regs which contains kernel stack pointer.
9140e084a5SRalf Baechle  * @addr:       address which is checked.
9240e084a5SRalf Baechle  *
9340e084a5SRalf Baechle  * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
9440e084a5SRalf Baechle  * If @addr is within the kernel stack, it returns true. If not, returns false.
9540e084a5SRalf Baechle  */
regs_within_kernel_stack(struct pt_regs * regs,unsigned long addr)9640e084a5SRalf Baechle static inline int regs_within_kernel_stack(struct pt_regs *regs,
9740e084a5SRalf Baechle                                            unsigned long addr)
9840e084a5SRalf Baechle {
9940e084a5SRalf Baechle 	return ((addr & ~(THREAD_SIZE - 1))  ==
10040e084a5SRalf Baechle 		(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
10140e084a5SRalf Baechle }
10240e084a5SRalf Baechle 
10340e084a5SRalf Baechle /**
10440e084a5SRalf Baechle  * regs_get_kernel_stack_nth() - get Nth entry of the stack
10540e084a5SRalf Baechle  * @regs:       pt_regs which contains kernel stack pointer.
10640e084a5SRalf Baechle  * @n:          stack entry number.
10740e084a5SRalf Baechle  *
10840e084a5SRalf Baechle  * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
10940e084a5SRalf Baechle  * is specified by @regs. If the @n th entry is NOT in the kernel stack,
11040e084a5SRalf Baechle  * this returns 0.
11140e084a5SRalf Baechle  */
regs_get_kernel_stack_nth(struct pt_regs * regs,unsigned int n)11240e084a5SRalf Baechle static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
11340e084a5SRalf Baechle                                                       unsigned int n)
11440e084a5SRalf Baechle {
11540e084a5SRalf Baechle 	unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
11640e084a5SRalf Baechle 
11740e084a5SRalf Baechle 	addr += n;
11840e084a5SRalf Baechle 	if (regs_within_kernel_stack(regs, (unsigned long)addr))
11940e084a5SRalf Baechle 		return *addr;
12040e084a5SRalf Baechle 	else
12140e084a5SRalf Baechle 		return 0;
12240e084a5SRalf Baechle }
12340e084a5SRalf Baechle 
1240926bf95SDavid Daney struct task_struct;
1250926bf95SDavid Daney 
126a79ebea6SAlex Smith extern int ptrace_getregs(struct task_struct *child,
127a79ebea6SAlex Smith 	struct user_pt_regs __user *data);
128a79ebea6SAlex Smith extern int ptrace_setregs(struct task_struct *child,
129a79ebea6SAlex Smith 	struct user_pt_regs __user *data);
130d302d05cSRalf Baechle 
131d302d05cSRalf Baechle extern int ptrace_getfpregs(struct task_struct *child, __u32 __user *data);
132d302d05cSRalf Baechle extern int ptrace_setfpregs(struct task_struct *child, __u32 __user *data);
133d302d05cSRalf Baechle 
1340926bf95SDavid Daney extern int ptrace_get_watch_regs(struct task_struct *child,
1350926bf95SDavid Daney 	struct pt_watch_regs __user *addr);
1360926bf95SDavid Daney extern int ptrace_set_watch_regs(struct task_struct *child,
1370926bf95SDavid Daney 	struct pt_watch_regs __user *addr);
1380926bf95SDavid Daney 
139384740dcSRalf Baechle /*
140384740dcSRalf Baechle  * Does the process account for user or for system time?
141384740dcSRalf Baechle  */
142384740dcSRalf Baechle #define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER)
143384740dcSRalf Baechle 
is_syscall_success(struct pt_regs * regs)144d7e7528bSEric Paris static inline int is_syscall_success(struct pt_regs *regs)
145d7e7528bSEric Paris {
146d7e7528bSEric Paris 	return !regs->regs[7];
147d7e7528bSEric Paris }
148d7e7528bSEric Paris 
regs_return_value(struct pt_regs * regs)149d7e7528bSEric Paris static inline long regs_return_value(struct pt_regs *regs)
150d7e7528bSEric Paris {
15174f1077bSMarcin Nowakowski 	if (is_syscall_success(regs) || !user_mode(regs))
152d7e7528bSEric Paris 		return regs->regs[2];
153d7e7528bSEric Paris 	else
154d7e7528bSEric Paris 		return -regs->regs[2];
155d7e7528bSEric Paris }
156d7e7528bSEric Paris 
157384740dcSRalf Baechle #define instruction_pointer(regs) ((regs)->cp0_epc)
158fdd12a80SJiaxun Yang extern unsigned long exception_ip(struct pt_regs *regs);
159fdd12a80SJiaxun Yang #define exception_ip(regs) exception_ip(regs)
160384740dcSRalf Baechle #define profile_pc(regs) instruction_pointer(regs)
161384740dcSRalf Baechle 
162f91955daSJiaxun Yang extern asmlinkage long syscall_trace_enter(struct pt_regs *regs);
1638b659a39SRalf Baechle extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
164384740dcSRalf Baechle 
165ff2d8b19SJoe Perches extern void die(const char *, struct pt_regs *) __noreturn;
166384740dcSRalf Baechle 
die_if_kernel(const char * str,struct pt_regs * regs)167ce384d83SYury Polyanskiy static inline void die_if_kernel(const char *str, struct pt_regs *regs)
168384740dcSRalf Baechle {
169384740dcSRalf Baechle 	if (unlikely(!user_mode(regs)))
170384740dcSRalf Baechle 		die(str, regs);
171384740dcSRalf Baechle }
172384740dcSRalf Baechle 
173baf9ff74SRalf Baechle #define current_pt_regs()						\
174baf9ff74SRalf Baechle ({									\
175baf9ff74SRalf Baechle 	unsigned long sp = (unsigned long)__builtin_frame_address(0);	\
176baf9ff74SRalf Baechle 	(struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1;	\
177baf9ff74SRalf Baechle })
178baf9ff74SRalf Baechle 
179c0ff3c53SRalf Baechle /* Helpers for working with the user stack pointer */
180c0ff3c53SRalf Baechle 
user_stack_pointer(struct pt_regs * regs)181c0ff3c53SRalf Baechle static inline unsigned long user_stack_pointer(struct pt_regs *regs)
182c0ff3c53SRalf Baechle {
183c0ff3c53SRalf Baechle 	return regs->regs[29];
184c0ff3c53SRalf Baechle }
185c0ff3c53SRalf Baechle 
user_stack_pointer_set(struct pt_regs * regs,unsigned long val)186c0ff3c53SRalf Baechle static inline void user_stack_pointer_set(struct pt_regs *regs,
187c0ff3c53SRalf Baechle 	unsigned long val)
188c0ff3c53SRalf Baechle {
189c0ff3c53SRalf Baechle 	regs->regs[29] = val;
190c0ff3c53SRalf Baechle }
191c0ff3c53SRalf Baechle 
192384740dcSRalf Baechle #endif /* _ASM_PTRACE_H */
193