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 15struct 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 */ 70static inline unsigned long instruction_pointer(struct pt_regs *regs) 71{ 72 return regs->epc; 73} 74static 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 */ 83static inline unsigned long user_stack_pointer(struct pt_regs *regs) 84{ 85 return regs->sp; 86} 87static 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. */ 94static 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 */ 100static inline unsigned long frame_pointer(struct pt_regs *regs) 101{ 102 return regs->s0; 103} 104static inline void frame_pointer_set(struct pt_regs *regs, 105 unsigned long val) 106{ 107 regs->s0 = val; 108} 109 110static inline unsigned long regs_return_value(struct pt_regs *regs) 111{ 112 return regs->a0; 113} 114 115static inline void regs_set_return_value(struct pt_regs *regs, 116 unsigned long val) 117{ 118 regs->a0 = val; 119} 120 121extern int regs_query_register_offset(const char *name); 122extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, 123 unsigned int n); 124 125void 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 */ 137static 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 */ 156static 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 176static 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