aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel/ptrace.c')
-rw-r--r--arch/blackfin/kernel/ptrace.c113
1 files changed, 90 insertions, 23 deletions
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 9536c1e2d1c7..92b4ca0b5af6 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -9,9 +9,11 @@
9#include <linux/sched.h> 9#include <linux/sched.h>
10#include <linux/mm.h> 10#include <linux/mm.h>
11#include <linux/smp.h> 11#include <linux/smp.h>
12#include <linux/elf.h>
12#include <linux/errno.h> 13#include <linux/errno.h>
13#include <linux/ptrace.h> 14#include <linux/ptrace.h>
14#include <linux/user.h> 15#include <linux/user.h>
16#include <linux/regset.h>
15#include <linux/signal.h> 17#include <linux/signal.h>
16#include <linux/uaccess.h> 18#include <linux/uaccess.h>
17 19
@@ -50,22 +52,6 @@ static inline struct pt_regs *task_pt_regs(struct task_struct *task)
50} 52}
51 53
52/* 54/*
53 * Get all user integer registers.
54 */
55static inline int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
56{
57 struct pt_regs regs;
58 memcpy(&regs, task_pt_regs(tsk), sizeof(regs));
59 regs.usp = tsk->thread.usp;
60 return copy_to_user(uregs, &regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
61}
62
63/* Mapping from PT_xxx to the stack offset at which the register is
64 * saved. Notice that usp has no stack-slot and needs to be treated
65 * specially (see get_reg/put_reg below).
66 */
67
68/*
69 * Get contents of register REGNO in task TASK. 55 * Get contents of register REGNO in task TASK.
70 */ 56 */
71static inline long 57static inline long
@@ -170,6 +156,84 @@ static inline int is_user_addr_valid(struct task_struct *child,
170 return -EIO; 156 return -EIO;
171} 157}
172 158
159/*
160 * retrieve the contents of Blackfin userspace general registers
161 */
162static int genregs_get(struct task_struct *target,
163 const struct user_regset *regset,
164 unsigned int pos, unsigned int count,
165 void *kbuf, void __user *ubuf)
166{
167 struct pt_regs *regs = task_pt_regs(target);
168 int ret;
169
170 /* This sucks ... */
171 regs->usp = target->thread.usp;
172
173 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
174 regs, 0, sizeof(*regs));
175 if (ret < 0)
176 return ret;
177
178 return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
179 sizeof(*regs), -1);
180}
181
182/*
183 * update the contents of the Blackfin userspace general registers
184 */
185static int genregs_set(struct task_struct *target,
186 const struct user_regset *regset,
187 unsigned int pos, unsigned int count,
188 const void *kbuf, const void __user *ubuf)
189{
190 struct pt_regs *regs = task_pt_regs(target);
191 int ret;
192
193 /* Don't let people set SYSCFG (it's at the end of pt_regs) */
194 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
195 regs, 0, PT_SYSCFG);
196 if (ret < 0)
197 return ret;
198
199 /* This sucks ... */
200 target->thread.usp = regs->usp;
201 /* regs->retx = regs->pc; */
202
203 return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
204 PT_SYSCFG, -1);
205}
206
207/*
208 * Define the register sets available on the Blackfin under Linux
209 */
210enum bfin_regset {
211 REGSET_GENERAL,
212};
213
214static const struct user_regset bfin_regsets[] = {
215 [REGSET_GENERAL] = {
216 .core_note_type = NT_PRSTATUS,
217 .n = sizeof(struct pt_regs) / sizeof(long),
218 .size = sizeof(long),
219 .align = sizeof(long),
220 .get = genregs_get,
221 .set = genregs_set,
222 },
223};
224
225static const struct user_regset_view user_bfin_native_view = {
226 .name = "Blackfin",
227 .e_machine = EM_BLACKFIN,
228 .regsets = bfin_regsets,
229 .n = ARRAY_SIZE(bfin_regsets),
230};
231
232const struct user_regset_view *task_user_regset_view(struct task_struct *task)
233{
234 return &user_bfin_native_view;
235}
236
173void ptrace_enable(struct task_struct *child) 237void ptrace_enable(struct task_struct *child)
174{ 238{
175 struct pt_regs *regs = task_pt_regs(child); 239 struct pt_regs *regs = task_pt_regs(child);
@@ -327,15 +391,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
327 break; 391 break;
328 392
329 case PTRACE_GETREGS: 393 case PTRACE_GETREGS:
330 /* Get all gp regs from the child. */ 394 pr_debug("ptrace: PTRACE_GETREGS\n");
331 ret = ptrace_getregs(child, datap); 395 return copy_regset_to_user(child, &user_bfin_native_view,
332 break; 396 REGSET_GENERAL,
397 0, sizeof(struct pt_regs),
398 (void __user *)data);
333 399
334 case PTRACE_SETREGS: 400 case PTRACE_SETREGS:
335 printk(KERN_WARNING "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n"); 401 pr_debug("ptrace: PTRACE_SETREGS\n");
336 /* Set all gp regs in the child. */ 402 return copy_regset_from_user(child, &user_bfin_native_view,
337 ret = 0; 403 REGSET_GENERAL,
338 break; 404 0, sizeof(struct pt_regs),
405 (const void __user *)data);
339 406
340 default: 407 default:
341 ret = ptrace_request(child, request, addr, data); 408 ret = ptrace_request(child, request, addr, data);