1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright (C) 2012 Regents of the University of California 4 */ 5 6 #ifndef _ASM_RISCV_PTRACE_H 7 #define _ASM_RISCV_PTRACE_H 8 9 #include <uapi/asm/ptrace.h> 10 #include <asm/csr.h> 11 #include <linux/compiler.h> 12 13 #ifndef __ASSEMBLY__ 14 15 struct pt_regs { 16 unsigned long epc; 17 unsigned long ra; 18 unsigned long sp; 19 unsigned long gp; 20 unsigned long tp; 21 unsigned long t0; 22 unsigned long t1; 23 unsigned long t2; 24 unsigned long s0; 25 unsigned long s1; 26 unsigned long a0; 27 unsigned long a1; 28 unsigned long a2; 29 unsigned long a3; 30 unsigned long a4; 31 unsigned long a5; 32 unsigned long a6; 33 unsigned long a7; 34 unsigned long s2; 35 unsigned long s3; 36 unsigned long s4; 37 unsigned long s5; 38 unsigned long s6; 39 unsigned long s7; 40 unsigned long s8; 41 unsigned long s9; 42 unsigned long s10; 43 unsigned long s11; 44 unsigned long t3; 45 unsigned long t4; 46 unsigned long t5; 47 unsigned long t6; 48 /* Supervisor/Machine CSRs */ 49 unsigned long status; 50 unsigned long badaddr; 51 unsigned long cause; 52 /* a0 value before the syscall */ 53 unsigned long orig_a0; 54 }; 55 56 #ifdef CONFIG_64BIT 57 #define REG_FMT "%016lx" 58 #else 59 #define REG_FMT "%08lx" 60 #endif 61 62 #define user_mode(regs) (((regs)->status & SR_PP) == 0) 63 64 #define MAX_REG_OFFSET offsetof(struct pt_regs, orig_a0) 65 66 /* Helpers for working with the instruction pointer */ 67 static inline unsigned long instruction_pointer(struct pt_regs *regs) 68 { 69 return regs->epc; 70 } 71 static inline void instruction_pointer_set(struct pt_regs *regs, 72 unsigned long val) 73 { 74 regs->epc = val; 75 } 76 77 #define profile_pc(regs) instruction_pointer(regs) 78 79 /* Helpers for working with the user stack pointer */ 80 static inline unsigned long user_stack_pointer(struct pt_regs *regs) 81 { 82 return regs->sp; 83 } 84 static inline void user_stack_pointer_set(struct pt_regs *regs, 85 unsigned long val) 86 { 87 regs->sp = val; 88 } 89 90 /* Valid only for Kernel mode traps. */ 91 static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) 92 { 93 return regs->sp; 94 } 95 96 /* Helpers for working with the frame pointer */ 97 static inline unsigned long frame_pointer(struct pt_regs *regs) 98 { 99 return regs->s0; 100 } 101 static inline void frame_pointer_set(struct pt_regs *regs, 102 unsigned long val) 103 { 104 regs->s0 = val; 105 } 106 107 static inline unsigned long regs_return_value(struct pt_regs *regs) 108 { 109 return regs->a0; 110 } 111 112 static inline void regs_set_return_value(struct pt_regs *regs, 113 unsigned long val) 114 { 115 regs->a0 = val; 116 } 117 118 extern int regs_query_register_offset(const char *name); 119 extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, 120 unsigned int n); 121 122 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, 123 unsigned long frame_pointer); 124 int do_syscall_trace_enter(struct pt_regs *regs); 125 void do_syscall_trace_exit(struct pt_regs *regs); 126 127 /** 128 * regs_get_register() - get register value from its offset 129 * @regs: pt_regs from which register value is gotten 130 * @offset: offset of the register. 131 * 132 * regs_get_register returns the value of a register whose offset from @regs. 133 * The @offset is the offset of the register in struct pt_regs. 134 * If @offset is bigger than MAX_REG_OFFSET, this returns 0. 135 */ 136 static inline unsigned long regs_get_register(struct pt_regs *regs, 137 unsigned int offset) 138 { 139 if (unlikely(offset > MAX_REG_OFFSET)) 140 return 0; 141 142 return *(unsigned long *)((unsigned long)regs + offset); 143 } 144 145 /** 146 * regs_get_kernel_argument() - get Nth function argument in kernel 147 * @regs: pt_regs of that context 148 * @n: function argument number (start from 0) 149 * 150 * regs_get_argument() returns @n th argument of the function call. 151 * 152 * Note you can get the parameter correctly if the function has no 153 * more than eight arguments. 154 */ 155 static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs, 156 unsigned int n) 157 { 158 static const int nr_reg_arguments = 8; 159 static const unsigned int argument_offs[] = { 160 offsetof(struct pt_regs, a0), 161 offsetof(struct pt_regs, a1), 162 offsetof(struct pt_regs, a2), 163 offsetof(struct pt_regs, a3), 164 offsetof(struct pt_regs, a4), 165 offsetof(struct pt_regs, a5), 166 offsetof(struct pt_regs, a6), 167 offsetof(struct pt_regs, a7), 168 }; 169 170 if (n < nr_reg_arguments) 171 return regs_get_register(regs, argument_offs[n]); 172 return 0; 173 } 174 175 #endif /* __ASSEMBLY__ */ 176 177 #endif /* _ASM_RISCV_PTRACE_H */ 178