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