xref: /openbmc/linux/arch/arc/include/asm/ptrace.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1d2912cb1SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
23be80aaeSVineet Gupta /*
33be80aaeSVineet Gupta  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
43be80aaeSVineet Gupta  *
53be80aaeSVineet Gupta  * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
63be80aaeSVineet Gupta  */
73be80aaeSVineet Gupta #ifndef __ASM_ARC_PTRACE_H
83be80aaeSVineet Gupta #define __ASM_ARC_PTRACE_H
93be80aaeSVineet Gupta 
108c2f4a8dSVineet Gupta #include <uapi/asm/ptrace.h>
11b3bbf6a7SSergey Matyukevich #include <linux/compiler.h>
123be80aaeSVineet Gupta 
133be80aaeSVineet Gupta #ifndef __ASSEMBLY__
143be80aaeSVineet Gupta 
15*58d9ceb7SVineet Gupta typedef union {
16*58d9ceb7SVineet Gupta 	struct {
17*58d9ceb7SVineet Gupta #ifdef CONFIG_CPU_BIG_ENDIAN
18*58d9ceb7SVineet Gupta 		unsigned long state:8, vec:8, cause:8, param:8;
19*58d9ceb7SVineet Gupta #else
20*58d9ceb7SVineet Gupta 		unsigned long param:8, cause:8, vec:8, state:8;
21*58d9ceb7SVineet Gupta #endif
22*58d9ceb7SVineet Gupta 	};
23*58d9ceb7SVineet Gupta 	unsigned long full;
24*58d9ceb7SVineet Gupta } ecr_reg;
25*58d9ceb7SVineet Gupta 
263be80aaeSVineet Gupta /* THE pt_regs: Defines how regs are saved during entry into kernel */
273be80aaeSVineet Gupta 
281f6ccfffSVineet Gupta #ifdef CONFIG_ISA_ARCOMPACT
293be80aaeSVineet Gupta struct pt_regs {
303be80aaeSVineet Gupta 
313be80aaeSVineet Gupta 	/* Real registers */
3287ce6280SVineet Gupta 	unsigned long bta;	/* bta_l1, bta_l2, erbta */
334b06ff35SVineet Gupta 
3487ce6280SVineet Gupta 	unsigned long lp_start, lp_end, lp_count;
354b06ff35SVineet Gupta 
3687ce6280SVineet Gupta 	unsigned long status32;	/* status32_l1, status32_l2, erstatus */
3787ce6280SVineet Gupta 	unsigned long ret;	/* ilink1, ilink2 or eret */
3887ce6280SVineet Gupta 	unsigned long blink;
3987ce6280SVineet Gupta 	unsigned long fp;
4087ce6280SVineet Gupta 	unsigned long r26;	/* gp */
414b06ff35SVineet Gupta 
4287ce6280SVineet Gupta 	unsigned long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
434b06ff35SVineet Gupta 
4487ce6280SVineet Gupta 	unsigned long sp;	/* User/Kernel depending on where we came from */
4587ce6280SVineet Gupta 	unsigned long orig_r0;
465c39c0abSVineet Gupta 
47502a0c77SVineet Gupta 	/*
48502a0c77SVineet Gupta 	 * To distinguish bet excp, syscall, irq
49502a0c77SVineet Gupta 	 * For traps and exceptions, Exception Cause Register.
50502a0c77SVineet Gupta 	 * 	ECR: <00> <VV> <CC> <PP>
51502a0c77SVineet Gupta 	 * 	Last word used by Linux for extra state mgmt (syscall-restart)
52502a0c77SVineet Gupta 	 * For interrupts, use artificial ECR values to note current prio-level
53502a0c77SVineet Gupta 	 */
54*58d9ceb7SVineet Gupta 	ecr_reg ecr;
553be80aaeSVineet Gupta };
56b3bbf6a7SSergey Matyukevich 
57*58d9ceb7SVineet Gupta #define MAX_REG_OFFSET offsetof(struct pt_regs, ecr)
58b3bbf6a7SSergey Matyukevich 
591f6ccfffSVineet Gupta #else
601f6ccfffSVineet Gupta 
611f6ccfffSVineet Gupta struct pt_regs {
621f6ccfffSVineet Gupta 
6387ce6280SVineet Gupta 	unsigned long orig_r0;
641f6ccfffSVineet Gupta 
65*58d9ceb7SVineet Gupta 	ecr_reg ecr;		/* Exception Cause Reg */
661f6ccfffSVineet Gupta 
67c505b0daSVineet Gupta 	unsigned long bta;	/* erbta */
681f6ccfffSVineet Gupta 
6987ce6280SVineet Gupta 	unsigned long fp;
70d4624bf6SVineet Gupta 	unsigned long r30;
71d4624bf6SVineet Gupta 	unsigned long r12;
72d4624bf6SVineet Gupta 	unsigned long r26;	/* gp */
731f6ccfffSVineet Gupta 
743d5e8012SVineet Gupta #ifdef CONFIG_ARC_HAS_ACCL_REGS
753d5e8012SVineet Gupta 	unsigned long r58, r59;	/* ACCL/ACCH used by FPU / DSP MPY */
763d5e8012SVineet Gupta #endif
777321e2eaSEugeniy Paltsev #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS
787321e2eaSEugeniy Paltsev 	unsigned long DSP_CTRL;
797321e2eaSEugeniy Paltsev #endif
803d5e8012SVineet Gupta 
81d4624bf6SVineet Gupta 	unsigned long sp;	/* user/kernel sp depending on entry  */
82d4624bf6SVineet Gupta 
831f6ccfffSVineet Gupta 	/*------- Below list auto saved by h/w -----------*/
8487ce6280SVineet Gupta 	unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
851f6ccfffSVineet Gupta 
8687ce6280SVineet Gupta 	unsigned long blink;
8787ce6280SVineet Gupta 	unsigned long lp_end, lp_start, lp_count;
881f6ccfffSVineet Gupta 
8987ce6280SVineet Gupta 	unsigned long ei, ldi, jli;
901f6ccfffSVineet Gupta 
9187ce6280SVineet Gupta 	unsigned long ret;
9287ce6280SVineet Gupta 	unsigned long status32;
931f6ccfffSVineet Gupta };
941f6ccfffSVineet Gupta 
95b3bbf6a7SSergey Matyukevich #define MAX_REG_OFFSET offsetof(struct pt_regs, status32)
96b3bbf6a7SSergey Matyukevich 
971f6ccfffSVineet Gupta #endif
983be80aaeSVineet Gupta 
993be80aaeSVineet Gupta /* Callee saved registers - need to be saved only when you are scheduled out */
1003be80aaeSVineet Gupta 
1013be80aaeSVineet Gupta struct callee_regs {
10287ce6280SVineet Gupta 	unsigned long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13;
1033be80aaeSVineet Gupta };
1043be80aaeSVineet Gupta 
10587ce6280SVineet Gupta #define instruction_pointer(regs)	((regs)->ret)
1063be80aaeSVineet Gupta #define profile_pc(regs)		instruction_pointer(regs)
1073be80aaeSVineet Gupta 
1083be80aaeSVineet Gupta /* return 1 if user mode or 0 if kernel mode */
1093be80aaeSVineet Gupta #define user_mode(regs) (regs->status32 & STATUS_U_MASK)
1103be80aaeSVineet Gupta 
1113be80aaeSVineet Gupta #define user_stack_pointer(regs)\
1123be80aaeSVineet Gupta ({  unsigned int sp;		\
1133be80aaeSVineet Gupta 	if (user_mode(regs))	\
1143be80aaeSVineet Gupta 		sp = (regs)->sp;\
1153be80aaeSVineet Gupta 	else			\
1163be80aaeSVineet Gupta 		sp = -1;	\
1173be80aaeSVineet Gupta 	sp;			\
1183be80aaeSVineet Gupta })
1194adeefe1SVineet Gupta 
1202e651ea1SVineet Gupta /* return 1 if PC in delay slot */
1212e651ea1SVineet Gupta #define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK)
1222e651ea1SVineet Gupta 
123*58d9ceb7SVineet Gupta #define in_syscall(regs)    ((regs->ecr.vec == ECR_V_TRAP) && !regs->ecr.param)
124*58d9ceb7SVineet Gupta #define in_brkpt_trap(regs) ((regs->ecr.vec == ECR_V_TRAP) && regs->ecr.param)
1254adeefe1SVineet Gupta 
126502a0c77SVineet Gupta #define STATE_SCALL_RESTARTED	0x01
127502a0c77SVineet Gupta 
128*58d9ceb7SVineet Gupta #define syscall_wont_restart(regs) (regs->ecr.state |= STATE_SCALL_RESTARTED)
129*58d9ceb7SVineet Gupta #define syscall_restartable(regs) !(regs->ecr.state &  STATE_SCALL_RESTARTED)
13055bb9480SVineet Gupta 
131bf90e1eaSVineet Gupta #define current_pt_regs()					\
132bf90e1eaSVineet Gupta ({								\
133bf90e1eaSVineet Gupta 	/* open-coded current_thread_info() */			\
134bf90e1eaSVineet Gupta 	register unsigned long sp asm ("sp");			\
135bf90e1eaSVineet Gupta 	unsigned long pg_start = (sp & ~(THREAD_SIZE - 1));	\
136283237a0SVineet Gupta 	(struct pt_regs *)(pg_start + THREAD_SIZE) - 1;	\
137bf90e1eaSVineet Gupta })
138bf90e1eaSVineet Gupta 
regs_return_value(struct pt_regs * regs)1394d86dfbbSVineet Gupta static inline long regs_return_value(struct pt_regs *regs)
1404d86dfbbSVineet Gupta {
14187ce6280SVineet Gupta 	return (long)regs->r0;
1424d86dfbbSVineet Gupta }
1434d86dfbbSVineet Gupta 
instruction_pointer_set(struct pt_regs * regs,unsigned long val)144bb6121b1SMasami Hiramatsu static inline void instruction_pointer_set(struct pt_regs *regs,
145bb6121b1SMasami Hiramatsu 					   unsigned long val)
146bb6121b1SMasami Hiramatsu {
147bb6121b1SMasami Hiramatsu 	instruction_pointer(regs) = val;
148bb6121b1SMasami Hiramatsu }
149b3bbf6a7SSergey Matyukevich 
kernel_stack_pointer(struct pt_regs * regs)150b3bbf6a7SSergey Matyukevich static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
151b3bbf6a7SSergey Matyukevich {
152b3bbf6a7SSergey Matyukevich 	return regs->sp;
153b3bbf6a7SSergey Matyukevich }
154b3bbf6a7SSergey Matyukevich 
155b3bbf6a7SSergey Matyukevich extern int regs_query_register_offset(const char *name);
156b3bbf6a7SSergey Matyukevich extern const char *regs_query_register_name(unsigned int offset);
157b3bbf6a7SSergey Matyukevich extern bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr);
158b3bbf6a7SSergey Matyukevich extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
159b3bbf6a7SSergey Matyukevich 					       unsigned int n);
160b3bbf6a7SSergey Matyukevich 
regs_get_register(struct pt_regs * regs,unsigned int offset)161b3bbf6a7SSergey Matyukevich static inline unsigned long regs_get_register(struct pt_regs *regs,
162b3bbf6a7SSergey Matyukevich 					      unsigned int offset)
163b3bbf6a7SSergey Matyukevich {
164b3bbf6a7SSergey Matyukevich 	if (unlikely(offset > MAX_REG_OFFSET))
165b3bbf6a7SSergey Matyukevich 		return 0;
166b3bbf6a7SSergey Matyukevich 
167b3bbf6a7SSergey Matyukevich 	return *(unsigned long *)((unsigned long)regs + offset);
168b3bbf6a7SSergey Matyukevich }
169b3bbf6a7SSergey Matyukevich 
1704d369680SVineet Gupta extern int syscall_trace_entry(struct pt_regs *);
1714d369680SVineet Gupta extern void syscall_trace_exit(struct pt_regs *);
1724d369680SVineet Gupta 
1733be80aaeSVineet Gupta #endif /* !__ASSEMBLY__ */
1743be80aaeSVineet Gupta 
1753be80aaeSVineet Gupta #endif /* __ASM_PTRACE_H */
176