Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
0004  *
0005  * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
0006  */
0007 #ifndef __ASM_ARC_PTRACE_H
0008 #define __ASM_ARC_PTRACE_H
0009 
0010 #include <uapi/asm/ptrace.h>
0011 #include <linux/compiler.h>
0012 
0013 #ifndef __ASSEMBLY__
0014 
0015 /* THE pt_regs: Defines how regs are saved during entry into kernel */
0016 
0017 #ifdef CONFIG_ISA_ARCOMPACT
0018 struct pt_regs {
0019 
0020     /* Real registers */
0021     unsigned long bta;  /* bta_l1, bta_l2, erbta */
0022 
0023     unsigned long lp_start, lp_end, lp_count;
0024 
0025     unsigned long status32; /* status32_l1, status32_l2, erstatus */
0026     unsigned long ret;  /* ilink1, ilink2 or eret */
0027     unsigned long blink;
0028     unsigned long fp;
0029     unsigned long r26;  /* gp */
0030 
0031     unsigned long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
0032 
0033     unsigned long sp;   /* User/Kernel depending on where we came from */
0034     unsigned long orig_r0;
0035 
0036     /*
0037      * To distinguish bet excp, syscall, irq
0038      * For traps and exceptions, Exception Cause Register.
0039      *  ECR: <00> <VV> <CC> <PP>
0040      *  Last word used by Linux for extra state mgmt (syscall-restart)
0041      * For interrupts, use artificial ECR values to note current prio-level
0042      */
0043     union {
0044         struct {
0045 #ifdef CONFIG_CPU_BIG_ENDIAN
0046             unsigned long state:8, ecr_vec:8,
0047                       ecr_cause:8, ecr_param:8;
0048 #else
0049             unsigned long ecr_param:8, ecr_cause:8,
0050                       ecr_vec:8, state:8;
0051 #endif
0052         };
0053         unsigned long event;
0054     };
0055 
0056     unsigned long user_r25;
0057 };
0058 
0059 #define MAX_REG_OFFSET offsetof(struct pt_regs, user_r25)
0060 
0061 #else
0062 
0063 struct pt_regs {
0064 
0065     unsigned long orig_r0;
0066 
0067     union {
0068         struct {
0069 #ifdef CONFIG_CPU_BIG_ENDIAN
0070             unsigned long state:8, ecr_vec:8,
0071                       ecr_cause:8, ecr_param:8;
0072 #else
0073             unsigned long ecr_param:8, ecr_cause:8,
0074                       ecr_vec:8, state:8;
0075 #endif
0076         };
0077         unsigned long event;
0078     };
0079 
0080     unsigned long bta;  /* bta_l1, bta_l2, erbta */
0081 
0082     unsigned long user_r25;
0083 
0084     unsigned long r26;  /* gp */
0085     unsigned long fp;
0086     unsigned long sp;   /* user/kernel sp depending on where we came from  */
0087 
0088     unsigned long r12, r30;
0089 
0090 #ifdef CONFIG_ARC_HAS_ACCL_REGS
0091     unsigned long r58, r59; /* ACCL/ACCH used by FPU / DSP MPY */
0092 #endif
0093 #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS
0094     unsigned long DSP_CTRL;
0095 #endif
0096 
0097     /*------- Below list auto saved by h/w -----------*/
0098     unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
0099 
0100     unsigned long blink;
0101     unsigned long lp_end, lp_start, lp_count;
0102 
0103     unsigned long ei, ldi, jli;
0104 
0105     unsigned long ret;
0106     unsigned long status32;
0107 };
0108 
0109 #define MAX_REG_OFFSET offsetof(struct pt_regs, status32)
0110 
0111 #endif
0112 
0113 /* Callee saved registers - need to be saved only when you are scheduled out */
0114 
0115 struct callee_regs {
0116     unsigned long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13;
0117 };
0118 
0119 #define instruction_pointer(regs)   ((regs)->ret)
0120 #define profile_pc(regs)        instruction_pointer(regs)
0121 
0122 /* return 1 if user mode or 0 if kernel mode */
0123 #define user_mode(regs) (regs->status32 & STATUS_U_MASK)
0124 
0125 #define user_stack_pointer(regs)\
0126 ({  unsigned int sp;        \
0127     if (user_mode(regs))    \
0128         sp = (regs)->sp;\
0129     else            \
0130         sp = -1;    \
0131     sp;         \
0132 })
0133 
0134 /* return 1 if PC in delay slot */
0135 #define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK)
0136 
0137 #define in_syscall(regs)    ((regs->ecr_vec == ECR_V_TRAP) && !regs->ecr_param)
0138 #define in_brkpt_trap(regs) ((regs->ecr_vec == ECR_V_TRAP) && regs->ecr_param)
0139 
0140 #define STATE_SCALL_RESTARTED   0x01
0141 
0142 #define syscall_wont_restart(reg) (reg->state |= STATE_SCALL_RESTARTED)
0143 #define syscall_restartable(reg) !(reg->state &  STATE_SCALL_RESTARTED)
0144 
0145 #define current_pt_regs()                   \
0146 ({                              \
0147     /* open-coded current_thread_info() */          \
0148     register unsigned long sp asm ("sp");           \
0149     unsigned long pg_start = (sp & ~(THREAD_SIZE - 1)); \
0150     (struct pt_regs *)(pg_start + THREAD_SIZE) - 1; \
0151 })
0152 
0153 static inline long regs_return_value(struct pt_regs *regs)
0154 {
0155     return (long)regs->r0;
0156 }
0157 
0158 static inline void instruction_pointer_set(struct pt_regs *regs,
0159                        unsigned long val)
0160 {
0161     instruction_pointer(regs) = val;
0162 }
0163 
0164 static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
0165 {
0166     return regs->sp;
0167 }
0168 
0169 extern int regs_query_register_offset(const char *name);
0170 extern const char *regs_query_register_name(unsigned int offset);
0171 extern bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr);
0172 extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
0173                            unsigned int n);
0174 
0175 static inline unsigned long regs_get_register(struct pt_regs *regs,
0176                           unsigned int offset)
0177 {
0178     if (unlikely(offset > MAX_REG_OFFSET))
0179         return 0;
0180 
0181     return *(unsigned long *)((unsigned long)regs + offset);
0182 }
0183 
0184 #endif /* !__ASSEMBLY__ */
0185 
0186 #endif /* __ASM_PTRACE_H */