1
2
3
4
5
6
7
8#include <linux/kernel.h>
9#include <linux/sched.h>
10#include <linux/sched/task_stack.h>
11#include <linux/mm.h>
12#include <linux/smp.h>
13#include <linux/errno.h>
14#include <linux/ptrace.h>
15#include <linux/regset.h>
16#include <linux/user.h>
17#include <linux/elf.h>
18
19#include <asm/user.h>
20
21#if arch_has_single_step()
22
23void user_enable_single_step(struct task_struct *child)
24{
25 pt_set_singlestep(task_pt_regs(child));
26 set_tsk_thread_flag(child, TIF_SINGLESTEP);
27}
28
29void user_disable_single_step(struct task_struct *child)
30{
31 pt_clr_singlestep(task_pt_regs(child));
32 clear_tsk_thread_flag(child, TIF_SINGLESTEP);
33}
34#endif
35
36static int genregs_get(struct task_struct *target,
37 const struct user_regset *regset,
38 unsigned int pos, unsigned int count,
39 void *kbuf, void __user *ubuf)
40{
41 int ret;
42 unsigned int dummy;
43 struct pt_regs *regs = task_pt_regs(target);
44
45
46 if (!regs)
47 return -EIO;
48
49
50
51
52
53
54
55 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
56 ®s->r00, 0, 32*sizeof(unsigned long));
57
58#define ONEXT(KPT_REG, USR_REG) \
59 if (!ret) \
60 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, \
61 KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
62 offsetof(struct user_regs_struct, USR_REG) + \
63 sizeof(unsigned long));
64
65
66 ONEXT(®s->sa0, sa0);
67 ONEXT(®s->lc0, lc0);
68 ONEXT(®s->sa1, sa1);
69 ONEXT(®s->lc1, lc1);
70 ONEXT(®s->m0, m0);
71 ONEXT(®s->m1, m1);
72 ONEXT(®s->usr, usr);
73 ONEXT(®s->preds, p3_0);
74 ONEXT(®s->gp, gp);
75 ONEXT(®s->ugp, ugp);
76 ONEXT(&pt_elr(regs), pc);
77 dummy = pt_cause(regs);
78 ONEXT(&dummy, cause);
79 ONEXT(&pt_badva(regs), badva);
80#if CONFIG_HEXAGON_ARCH_VERSION >=4
81 ONEXT(®s->cs0, cs0);
82 ONEXT(®s->cs1, cs1);
83#endif
84
85
86 if (!ret)
87 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
88 offsetof(struct user_regs_struct, pad1), -1);
89 return ret;
90}
91
92static int genregs_set(struct task_struct *target,
93 const struct user_regset *regset,
94 unsigned int pos, unsigned int count,
95 const void *kbuf, const void __user *ubuf)
96{
97 int ret;
98 unsigned long bucket;
99 struct pt_regs *regs = task_pt_regs(target);
100
101 if (!regs)
102 return -EIO;
103
104 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
105 ®s->r00, 0, 32*sizeof(unsigned long));
106
107#define INEXT(KPT_REG, USR_REG) \
108 if (!ret) \
109 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
110 KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
111 offsetof(struct user_regs_struct, USR_REG) + \
112 sizeof(unsigned long));
113
114
115 INEXT(®s->sa0, sa0);
116 INEXT(®s->lc0, lc0);
117 INEXT(®s->sa1, sa1);
118 INEXT(®s->lc1, lc1);
119 INEXT(®s->m0, m0);
120 INEXT(®s->m1, m1);
121 INEXT(®s->usr, usr);
122 INEXT(®s->preds, p3_0);
123 INEXT(®s->gp, gp);
124 INEXT(®s->ugp, ugp);
125 INEXT(&pt_elr(regs), pc);
126
127
128 INEXT(&bucket, cause);
129 INEXT(&bucket, badva);
130
131#if CONFIG_HEXAGON_ARCH_VERSION >=4
132 INEXT(®s->cs0, cs0);
133 INEXT(®s->cs1, cs1);
134#endif
135
136
137 if (!ret)
138 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
139 offsetof(struct user_regs_struct, pad1), -1);
140
141 if (ret)
142 return ret;
143
144
145
146
147
148 regs->hvmer.vmpsp = regs->r29;
149 return 0;
150}
151
152enum hexagon_regset {
153 REGSET_GENERAL,
154};
155
156static const struct user_regset hexagon_regsets[] = {
157 [REGSET_GENERAL] = {
158 .core_note_type = NT_PRSTATUS,
159 .n = ELF_NGREG,
160 .size = sizeof(unsigned long),
161 .align = sizeof(unsigned long),
162 .get = genregs_get,
163 .set = genregs_set,
164 },
165};
166
167static const struct user_regset_view hexagon_user_view = {
168 .name = "hexagon",
169 .e_machine = ELF_ARCH,
170 .ei_osabi = ELF_OSABI,
171 .regsets = hexagon_regsets,
172 .e_flags = ELF_CORE_EFLAGS,
173 .n = ARRAY_SIZE(hexagon_regsets)
174};
175
176const struct user_regset_view *task_user_regset_view(struct task_struct *task)
177{
178 return &hexagon_user_view;
179}
180
181void ptrace_disable(struct task_struct *child)
182{
183
184 user_disable_single_step(child);
185}
186
187long arch_ptrace(struct task_struct *child, long request,
188 unsigned long addr, unsigned long data)
189{
190 return ptrace_request(child, request, addr, data);
191}
192