aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2010-02-14 17:58:02 -0500
committerMike Frysinger <vapier@gentoo.org>2010-03-09 00:30:51 -0500
commite50e2f25c5b90abd00a1e5871c45094cf5207afc (patch)
tree22c550f642bbc390c4713fa7d0dd8e1bab2ea4a0 /arch/blackfin
parentf2ce48024a9a6d3e92a023ded0f7b1e99da1cd16 (diff)
Blackfin: initial regset support
We don't support core dumps (yet?), but this should make things easier. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin')
-rw-r--r--arch/blackfin/include/asm/elf.h8
-rw-r--r--arch/blackfin/kernel/process.c7
-rw-r--r--arch/blackfin/kernel/ptrace.c113
3 files changed, 97 insertions, 31 deletions
diff --git a/arch/blackfin/include/asm/elf.h b/arch/blackfin/include/asm/elf.h
index 5b50f0ecacf8..117713adea7f 100644
--- a/arch/blackfin/include/asm/elf.h
+++ b/arch/blackfin/include/asm/elf.h
@@ -22,12 +22,15 @@
22#define EF_BFIN_CODE_IN_L2 0x00000040 /* --code-in-l2 */ 22#define EF_BFIN_CODE_IN_L2 0x00000040 /* --code-in-l2 */
23#define EF_BFIN_DATA_IN_L2 0x00000080 /* --data-in-l2 */ 23#define EF_BFIN_DATA_IN_L2 0x00000080 /* --data-in-l2 */
24 24
25#if 1 /* core dumps not supported, but linux/elfcore.h needs these */
25typedef unsigned long elf_greg_t; 26typedef unsigned long elf_greg_t;
26 27
27#define ELF_NGREG 40 /* (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) */ 28#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
28typedef elf_greg_t elf_gregset_t[ELF_NGREG]; 29typedef elf_greg_t elf_gregset_t[ELF_NGREG];
29 30
30typedef struct { } elf_fpregset_t; 31typedef struct { } elf_fpregset_t;
32#endif
33
31/* 34/*
32 * This is used to ensure we don't load something for the wrong architecture. 35 * This is used to ensure we don't load something for the wrong architecture.
33 */ 36 */
@@ -55,6 +58,9 @@ do { \
55 _regs->p2 = _dynamic_addr; \ 58 _regs->p2 = _dynamic_addr; \
56} while(0) 59} while(0)
57 60
61#if 0
62#define CORE_DUMP_USE_REGSET
63#endif
58#define ELF_FDPIC_CORE_EFLAGS EF_BFIN_FDPIC 64#define ELF_FDPIC_CORE_EFLAGS EF_BFIN_FDPIC
59#define ELF_EXEC_PAGESIZE 4096 65#define ELF_EXEC_PAGESIZE 4096
60 66
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index b56b0e485e0b..29705cec91de 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -98,13 +98,6 @@ void cpu_idle(void)
98 } 98 }
99} 99}
100 100
101/* Fill in the fpu structure for a core dump. */
102
103int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpregs)
104{
105 return 1;
106}
107
108/* 101/*
109 * This gets run with P1 containing the 102 * This gets run with P1 containing the
110 * function to call, and R1 containing 103 * function to call, and R1 containing
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);