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