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