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