xref: /openbmc/linux/arch/riscv/include/asm/ptrace.h (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
150acfb2bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2e2c0cdfbSPalmer Dabbelt /*
3e2c0cdfbSPalmer Dabbelt  * Copyright (C) 2012 Regents of the University of California
4e2c0cdfbSPalmer Dabbelt  */
5e2c0cdfbSPalmer Dabbelt 
6e2c0cdfbSPalmer Dabbelt #ifndef _ASM_RISCV_PTRACE_H
7e2c0cdfbSPalmer Dabbelt #define _ASM_RISCV_PTRACE_H
8e2c0cdfbSPalmer Dabbelt 
9e2c0cdfbSPalmer Dabbelt #include <uapi/asm/ptrace.h>
10e2c0cdfbSPalmer Dabbelt #include <asm/csr.h>
11dcdc7a53SPatrick Stählin #include <linux/compiler.h>
12e2c0cdfbSPalmer Dabbelt 
13e2c0cdfbSPalmer Dabbelt #ifndef __ASSEMBLY__
14e2c0cdfbSPalmer Dabbelt 
15e2c0cdfbSPalmer Dabbelt struct pt_regs {
16a4c3733dSChristoph Hellwig 	unsigned long epc;
17e2c0cdfbSPalmer Dabbelt 	unsigned long ra;
18e2c0cdfbSPalmer Dabbelt 	unsigned long sp;
19e2c0cdfbSPalmer Dabbelt 	unsigned long gp;
20e2c0cdfbSPalmer Dabbelt 	unsigned long tp;
21e2c0cdfbSPalmer Dabbelt 	unsigned long t0;
22e2c0cdfbSPalmer Dabbelt 	unsigned long t1;
23e2c0cdfbSPalmer Dabbelt 	unsigned long t2;
24e2c0cdfbSPalmer Dabbelt 	unsigned long s0;
25e2c0cdfbSPalmer Dabbelt 	unsigned long s1;
26e2c0cdfbSPalmer Dabbelt 	unsigned long a0;
27e2c0cdfbSPalmer Dabbelt 	unsigned long a1;
28e2c0cdfbSPalmer Dabbelt 	unsigned long a2;
29e2c0cdfbSPalmer Dabbelt 	unsigned long a3;
30e2c0cdfbSPalmer Dabbelt 	unsigned long a4;
31e2c0cdfbSPalmer Dabbelt 	unsigned long a5;
32e2c0cdfbSPalmer Dabbelt 	unsigned long a6;
33e2c0cdfbSPalmer Dabbelt 	unsigned long a7;
34e2c0cdfbSPalmer Dabbelt 	unsigned long s2;
35e2c0cdfbSPalmer Dabbelt 	unsigned long s3;
36e2c0cdfbSPalmer Dabbelt 	unsigned long s4;
37e2c0cdfbSPalmer Dabbelt 	unsigned long s5;
38e2c0cdfbSPalmer Dabbelt 	unsigned long s6;
39e2c0cdfbSPalmer Dabbelt 	unsigned long s7;
40e2c0cdfbSPalmer Dabbelt 	unsigned long s8;
41e2c0cdfbSPalmer Dabbelt 	unsigned long s9;
42e2c0cdfbSPalmer Dabbelt 	unsigned long s10;
43e2c0cdfbSPalmer Dabbelt 	unsigned long s11;
44e2c0cdfbSPalmer Dabbelt 	unsigned long t3;
45e2c0cdfbSPalmer Dabbelt 	unsigned long t4;
46e2c0cdfbSPalmer Dabbelt 	unsigned long t5;
47e2c0cdfbSPalmer Dabbelt 	unsigned long t6;
48a4c3733dSChristoph Hellwig 	/* Supervisor/Machine CSRs */
49a4c3733dSChristoph Hellwig 	unsigned long status;
50a4c3733dSChristoph Hellwig 	unsigned long badaddr;
51a4c3733dSChristoph Hellwig 	unsigned long cause;
52e2c0cdfbSPalmer Dabbelt 	/* a0 value before the syscall */
53e2c0cdfbSPalmer Dabbelt 	unsigned long orig_a0;
54e2c0cdfbSPalmer Dabbelt };
55e2c0cdfbSPalmer Dabbelt 
56*f0bddf50SGuo Ren #define PTRACE_SYSEMU			0x1f
57*f0bddf50SGuo Ren #define PTRACE_SYSEMU_SINGLESTEP	0x20
58*f0bddf50SGuo Ren 
59e2c0cdfbSPalmer Dabbelt #ifdef CONFIG_64BIT
60e2c0cdfbSPalmer Dabbelt #define REG_FMT "%016lx"
61e2c0cdfbSPalmer Dabbelt #else
62e2c0cdfbSPalmer Dabbelt #define REG_FMT "%08lx"
63e2c0cdfbSPalmer Dabbelt #endif
64e2c0cdfbSPalmer Dabbelt 
65a4c3733dSChristoph Hellwig #define user_mode(regs) (((regs)->status & SR_PP) == 0)
66e2c0cdfbSPalmer Dabbelt 
67dcdc7a53SPatrick Stählin #define MAX_REG_OFFSET offsetof(struct pt_regs, orig_a0)
68e2c0cdfbSPalmer Dabbelt 
69e2c0cdfbSPalmer Dabbelt /* Helpers for working with the instruction pointer */
instruction_pointer(struct pt_regs * regs)70e2c0cdfbSPalmer Dabbelt static inline unsigned long instruction_pointer(struct pt_regs *regs)
71e2c0cdfbSPalmer Dabbelt {
72a4c3733dSChristoph Hellwig 	return regs->epc;
73e2c0cdfbSPalmer Dabbelt }
instruction_pointer_set(struct pt_regs * regs,unsigned long val)74e2c0cdfbSPalmer Dabbelt static inline void instruction_pointer_set(struct pt_regs *regs,
75e2c0cdfbSPalmer Dabbelt 					   unsigned long val)
76e2c0cdfbSPalmer Dabbelt {
77a4c3733dSChristoph Hellwig 	regs->epc = val;
78e2c0cdfbSPalmer Dabbelt }
79e2c0cdfbSPalmer Dabbelt 
80e2c0cdfbSPalmer Dabbelt #define profile_pc(regs) instruction_pointer(regs)
81e2c0cdfbSPalmer Dabbelt 
82e2c0cdfbSPalmer Dabbelt /* Helpers for working with the user stack pointer */
user_stack_pointer(struct pt_regs * regs)83e2c0cdfbSPalmer Dabbelt static inline unsigned long user_stack_pointer(struct pt_regs *regs)
84e2c0cdfbSPalmer Dabbelt {
856ab77af4SChristoph Hellwig 	return regs->sp;
86e2c0cdfbSPalmer Dabbelt }
user_stack_pointer_set(struct pt_regs * regs,unsigned long val)87e2c0cdfbSPalmer Dabbelt static inline void user_stack_pointer_set(struct pt_regs *regs,
88e2c0cdfbSPalmer Dabbelt 					  unsigned long val)
89e2c0cdfbSPalmer Dabbelt {
906ab77af4SChristoph Hellwig 	regs->sp =  val;
91e2c0cdfbSPalmer Dabbelt }
92e2c0cdfbSPalmer Dabbelt 
93dcdc7a53SPatrick Stählin /* Valid only for Kernel mode traps. */
kernel_stack_pointer(struct pt_regs * regs)94dcdc7a53SPatrick Stählin static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
95dcdc7a53SPatrick Stählin {
96dcdc7a53SPatrick Stählin 	return regs->sp;
97dcdc7a53SPatrick Stählin }
98dcdc7a53SPatrick Stählin 
99e2c0cdfbSPalmer Dabbelt /* Helpers for working with the frame pointer */
frame_pointer(struct pt_regs * regs)100e2c0cdfbSPalmer Dabbelt static inline unsigned long frame_pointer(struct pt_regs *regs)
101e2c0cdfbSPalmer Dabbelt {
1026ab77af4SChristoph Hellwig 	return regs->s0;
103e2c0cdfbSPalmer Dabbelt }
frame_pointer_set(struct pt_regs * regs,unsigned long val)104e2c0cdfbSPalmer Dabbelt static inline void frame_pointer_set(struct pt_regs *regs,
105e2c0cdfbSPalmer Dabbelt 				     unsigned long val)
106e2c0cdfbSPalmer Dabbelt {
1076ab77af4SChristoph Hellwig 	regs->s0 = val;
108e2c0cdfbSPalmer Dabbelt }
109e2c0cdfbSPalmer Dabbelt 
regs_return_value(struct pt_regs * regs)110efe75c49SDavid Abdurachmanov static inline unsigned long regs_return_value(struct pt_regs *regs)
111efe75c49SDavid Abdurachmanov {
112efe75c49SDavid Abdurachmanov 	return regs->a0;
113efe75c49SDavid Abdurachmanov }
114efe75c49SDavid Abdurachmanov 
regs_set_return_value(struct pt_regs * regs,unsigned long val)115ee55ff80SGuo Ren static inline void regs_set_return_value(struct pt_regs *regs,
116ee55ff80SGuo Ren 					 unsigned long val)
117ee55ff80SGuo Ren {
118ee55ff80SGuo Ren 	regs->a0 = val;
119ee55ff80SGuo Ren }
120ee55ff80SGuo Ren 
121dcdc7a53SPatrick Stählin extern int regs_query_register_offset(const char *name);
122dcdc7a53SPatrick Stählin extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
123dcdc7a53SPatrick Stählin 					       unsigned int n);
124dcdc7a53SPatrick Stählin 
125e06f4ce1SNanyong Sun void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
126e06f4ce1SNanyong Sun 			   unsigned long frame_pointer);
127e06f4ce1SNanyong Sun 
128dcdc7a53SPatrick Stählin /**
129dcdc7a53SPatrick Stählin  * regs_get_register() - get register value from its offset
130dcdc7a53SPatrick Stählin  * @regs:	pt_regs from which register value is gotten
131dcdc7a53SPatrick Stählin  * @offset:	offset of the register.
132dcdc7a53SPatrick Stählin  *
133dcdc7a53SPatrick Stählin  * regs_get_register returns the value of a register whose offset from @regs.
134dcdc7a53SPatrick Stählin  * The @offset is the offset of the register in struct pt_regs.
135dcdc7a53SPatrick Stählin  * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
136dcdc7a53SPatrick Stählin  */
regs_get_register(struct pt_regs * regs,unsigned int offset)137dcdc7a53SPatrick Stählin static inline unsigned long regs_get_register(struct pt_regs *regs,
138dcdc7a53SPatrick Stählin 					      unsigned int offset)
139dcdc7a53SPatrick Stählin {
140dcdc7a53SPatrick Stählin 	if (unlikely(offset > MAX_REG_OFFSET))
141dcdc7a53SPatrick Stählin 		return 0;
142dcdc7a53SPatrick Stählin 
143dcdc7a53SPatrick Stählin 	return *(unsigned long *)((unsigned long)regs + offset);
144dcdc7a53SPatrick Stählin }
14570eee556SJeff Xie 
14670eee556SJeff Xie /**
14770eee556SJeff Xie  * regs_get_kernel_argument() - get Nth function argument in kernel
14870eee556SJeff Xie  * @regs:       pt_regs of that context
14970eee556SJeff Xie  * @n:          function argument number (start from 0)
15070eee556SJeff Xie  *
15170eee556SJeff Xie  * regs_get_argument() returns @n th argument of the function call.
15270eee556SJeff Xie  *
15370eee556SJeff Xie  * Note you can get the parameter correctly if the function has no
15470eee556SJeff Xie  * more than eight arguments.
15570eee556SJeff Xie  */
regs_get_kernel_argument(struct pt_regs * regs,unsigned int n)15670eee556SJeff Xie static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
15770eee556SJeff Xie 						unsigned int n)
15870eee556SJeff Xie {
15970eee556SJeff Xie 	static const int nr_reg_arguments = 8;
16070eee556SJeff Xie 	static const unsigned int argument_offs[] = {
16170eee556SJeff Xie 		offsetof(struct pt_regs, a0),
16270eee556SJeff Xie 		offsetof(struct pt_regs, a1),
16370eee556SJeff Xie 		offsetof(struct pt_regs, a2),
16470eee556SJeff Xie 		offsetof(struct pt_regs, a3),
16570eee556SJeff Xie 		offsetof(struct pt_regs, a4),
16670eee556SJeff Xie 		offsetof(struct pt_regs, a5),
16770eee556SJeff Xie 		offsetof(struct pt_regs, a6),
16870eee556SJeff Xie 		offsetof(struct pt_regs, a7),
16970eee556SJeff Xie 	};
17070eee556SJeff Xie 
17170eee556SJeff Xie 	if (n < nr_reg_arguments)
17270eee556SJeff Xie 		return regs_get_register(regs, argument_offs[n]);
17370eee556SJeff Xie 	return 0;
17470eee556SJeff Xie }
17570eee556SJeff Xie 
regs_irqs_disabled(struct pt_regs * regs)176*f0bddf50SGuo Ren static inline int regs_irqs_disabled(struct pt_regs *regs)
177*f0bddf50SGuo Ren {
178*f0bddf50SGuo Ren 	return !(regs->status & SR_PIE);
179*f0bddf50SGuo Ren }
180*f0bddf50SGuo Ren 
181e2c0cdfbSPalmer Dabbelt #endif /* __ASSEMBLY__ */
182e2c0cdfbSPalmer Dabbelt 
183e2c0cdfbSPalmer Dabbelt #endif /* _ASM_RISCV_PTRACE_H */
184