1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __SPARC_PTRACE_H #define __SPARC_PTRACE_H #include <uapi/asm/ptrace.h> #if defined(__sparc__) && defined(__arch64__) #ifndef __ASSEMBLY__ #include <linux/compiler.h> #include <linux/threads.h> #include <asm/switch_to.h> static inline int pt_regs_trap_type(struct pt_regs *regs) { return regs->magic & 0x1ff; } static inline bool pt_regs_is_syscall(struct pt_regs *regs) { return (regs->tstate & TSTATE_SYSCALL); } static inline bool pt_regs_clear_syscall(struct pt_regs *regs) { return (regs->tstate &= ~TSTATE_SYSCALL); } #define arch_ptrace_stop_needed(exit_code, info) \ ({ flush_user_windows(); \ get_thread_wsaved() != 0; \ }) #define arch_ptrace_stop(exit_code, info) \ synchronize_user_stack() #define current_pt_regs() \ ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) struct global_reg_snapshot { unsigned long tstate; unsigned long tpc; unsigned long tnpc; unsigned long o7; unsigned long i7; unsigned long rpc; struct thread_info *thread; unsigned long pad1; }; struct global_pmu_snapshot { unsigned long pcr[4]; unsigned long pic[4]; }; union global_cpu_snapshot { struct global_reg_snapshot reg; struct global_pmu_snapshot pmu; }; extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; #define force_successful_syscall_return() set_thread_noerror(1) #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) #define instruction_pointer(regs) ((regs)->tpc) #define instruction_pointer_set(regs, val) do { \ (regs)->tpc = (val); \ (regs)->tnpc = (val)+4; \ } while (0) #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) static inline int is_syscall_success(struct pt_regs *regs) { return !(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)); } static inline long regs_return_value(struct pt_regs *regs) { return regs->u_regs[UREG_I0]; } #ifdef [31mCONFIG_SMP[0m unsigned long profile_pc(struct pt_regs *); #else #define profile_pc(regs) instruction_pointer(regs) #endif #define MAX_REG_OFFSET (offsetof(struct pt_regs, magic)) int regs_query_register_offset(const char *name); unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n); /** * regs_get_register() - get register value from its offset * @regs: pt_regs from which register value is gotten * @offset: offset number of the register. * * regs_get_register returns the value of a register whose * offset from @regs. The @offset is the offset of the register * in struct pt_regs. If @offset is bigger than MAX_REG_OFFSET, * this returns 0. */ static inline unsigned long regs_get_register(struct pt_regs *regs, unsigned long offset) { if (unlikely(offset >= MAX_REG_OFFSET)) return 0; if (offset == PT_V9_Y) return *(unsigned int *)((unsigned long)regs + offset); return *(unsigned long *)((unsigned long)regs + offset); } /* Valid only for Kernel mode traps. */ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) { return regs->u_regs[UREG_I6]; } #else /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */ #else /* (defined(__sparc__) && defined(__arch64__)) */ #ifndef __ASSEMBLY__ #include <asm/switch_to.h> static inline bool pt_regs_is_syscall(struct pt_regs *regs) { return (regs->psr & PSR_SYSCALL); } static inline bool pt_regs_clear_syscall(struct pt_regs *regs) { return (regs->psr &= ~PSR_SYSCALL); } #define arch_ptrace_stop_needed(exit_code, info) \ ({ flush_user_windows(); \ current_thread_info()->w_saved != 0; \ }) #define arch_ptrace_stop(exit_code, info) \ synchronize_user_stack() #define current_pt_regs() \ ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) #define user_mode(regs) (!((regs)->psr & PSR_PS)) #define instruction_pointer(regs) ((regs)->pc) #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) unsigned long profile_pc(struct pt_regs *); #else /* (!__ASSEMBLY__) */ #endif /* (!__ASSEMBLY__) */ #endif /* (defined(__sparc__) && defined(__arch64__)) */ #define STACK_BIAS 2047 /* global_reg_snapshot offsets */ #define GR_SNAP_TSTATE 0x00 #define GR_SNAP_TPC 0x08 #define GR_SNAP_TNPC 0x10 #define GR_SNAP_O7 0x18 #define GR_SNAP_I7 0x20 #define GR_SNAP_RPC 0x28 #define GR_SNAP_THREAD 0x30 #define GR_SNAP_PAD1 0x38 #endif /* !(__SPARC_PTRACE_H) */ |