diff options
author | Chen Liqin <liqin.chen@sunplusct.com> | 2009-08-30 00:34:08 -0400 |
---|---|---|
committer | Chen Liqin <liqin.chen@sunplusct.com> | 2009-08-30 00:34:08 -0400 |
commit | 798983b2d5f9985655ca22a7a8c504b821e3f4e0 (patch) | |
tree | 29da57502bc8f662faabd1d2eb68bb94bcd34483 /arch | |
parent | cf52c468352993ca420fe0b4ada976dc1f614026 (diff) |
score: update files according to review comments.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/score/kernel/ptrace.c | 212 |
1 files changed, 97 insertions, 115 deletions
diff --git a/arch/score/kernel/ptrace.c b/arch/score/kernel/ptrace.c index 1db876b11476..174c6422b096 100644 --- a/arch/score/kernel/ptrace.c +++ b/arch/score/kernel/ptrace.c | |||
@@ -23,11 +23,100 @@ | |||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/elf.h> | ||
26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/mm.h> | ||
27 | #include <linux/ptrace.h> | 29 | #include <linux/ptrace.h> |
30 | #include <linux/regset.h> | ||
28 | 31 | ||
29 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
30 | 33 | ||
34 | /* | ||
35 | * retrieve the contents of SCORE userspace general registers | ||
36 | */ | ||
37 | static int genregs_get(struct task_struct *target, | ||
38 | const struct user_regset *regset, | ||
39 | unsigned int pos, unsigned int count, | ||
40 | void *kbuf, void __user *ubuf) | ||
41 | { | ||
42 | const struct pt_regs *regs = task_pt_regs(target); | ||
43 | int ret; | ||
44 | |||
45 | /* skip 9 * sizeof(unsigned long) not use for pt_regs */ | ||
46 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, | ||
47 | 0, offsetof(struct pt_regs, regs)); | ||
48 | |||
49 | /* r0 - r31, cel, ceh, sr0, sr1, sr2, epc, ema, psr, ecr, condition */ | ||
50 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
51 | regs->regs, | ||
52 | offsetof(struct pt_regs, regs), | ||
53 | offsetof(struct pt_regs, cp0_condition)); | ||
54 | |||
55 | if (!ret) | ||
56 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, | ||
57 | sizeof(struct pt_regs), -1); | ||
58 | |||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * update the contents of the SCORE userspace general registers | ||
64 | */ | ||
65 | static int genregs_set(struct task_struct *target, | ||
66 | const struct user_regset *regset, | ||
67 | unsigned int pos, unsigned int count, | ||
68 | const void *kbuf, const void __user *ubuf) | ||
69 | { | ||
70 | struct pt_regs *regs = task_pt_regs(target); | ||
71 | int ret; | ||
72 | |||
73 | /* skip 9 * sizeof(unsigned long) */ | ||
74 | ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, | ||
75 | 0, offsetof(struct pt_regs, regs)); | ||
76 | |||
77 | /* r0 - r31, cel, ceh, sr0, sr1, sr2, epc, ema, psr, ecr, condition */ | ||
78 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
79 | regs->regs, | ||
80 | offsetof(struct pt_regs, regs), | ||
81 | offsetof(struct pt_regs, cp0_condition)); | ||
82 | |||
83 | if (!ret) | ||
84 | ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, | ||
85 | sizeof(struct pt_regs), -1); | ||
86 | |||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * Define the register sets available on the score7 under Linux | ||
92 | */ | ||
93 | enum score7_regset { | ||
94 | REGSET_GENERAL, | ||
95 | }; | ||
96 | |||
97 | static const struct user_regset score7_regsets[] = { | ||
98 | [REGSET_GENERAL] = { | ||
99 | .core_note_type = NT_PRSTATUS, | ||
100 | .n = ELF_NGREG, | ||
101 | .size = sizeof(long), | ||
102 | .align = sizeof(long), | ||
103 | .get = genregs_get, | ||
104 | .set = genregs_set, | ||
105 | }, | ||
106 | }; | ||
107 | |||
108 | static const struct user_regset_view user_score_native_view = { | ||
109 | .name = "score7", | ||
110 | .e_machine = EM_SCORE7, | ||
111 | .regsets = score7_regsets, | ||
112 | .n = ARRAY_SIZE(score7_regsets), | ||
113 | }; | ||
114 | |||
115 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) | ||
116 | { | ||
117 | return &user_score_native_view; | ||
118 | } | ||
119 | |||
31 | static int is_16bitinsn(unsigned long insn) | 120 | static int is_16bitinsn(unsigned long insn) |
32 | { | 121 | { |
33 | if ((insn & INSN32_MASK) == INSN32_MASK) | 122 | if ((insn & INSN32_MASK) == INSN32_MASK) |
@@ -80,34 +169,6 @@ write_tsk_long(struct task_struct *child, | |||
80 | return copied != sizeof(val) ? -EIO : 0; | 169 | return copied != sizeof(val) ? -EIO : 0; |
81 | } | 170 | } |
82 | 171 | ||
83 | /* | ||
84 | * Get all user integer registers. | ||
85 | */ | ||
86 | static int ptrace_getregs(struct task_struct *tsk, void __user *uregs) | ||
87 | { | ||
88 | struct pt_regs *regs = task_pt_regs(tsk); | ||
89 | |||
90 | return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * Set all user integer registers. | ||
95 | */ | ||
96 | static int ptrace_setregs(struct task_struct *tsk, void __user *uregs) | ||
97 | { | ||
98 | struct pt_regs newregs; | ||
99 | int ret; | ||
100 | |||
101 | ret = -EFAULT; | ||
102 | if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) { | ||
103 | struct pt_regs *regs = task_pt_regs(tsk); | ||
104 | *regs = newregs; | ||
105 | ret = 0; | ||
106 | } | ||
107 | |||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | void user_enable_single_step(struct task_struct *child) | 172 | void user_enable_single_step(struct task_struct *child) |
112 | { | 173 | { |
113 | /* far_epc is the target of branch */ | 174 | /* far_epc is the target of branch */ |
@@ -270,97 +331,18 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
270 | unsigned long __user *datap = (void __user *)data; | 331 | unsigned long __user *datap = (void __user *)data; |
271 | 332 | ||
272 | switch (request) { | 333 | switch (request) { |
273 | /* Read the word at location addr in the USER area. */ | ||
274 | case PTRACE_PEEKUSR: { | ||
275 | struct pt_regs *regs; | ||
276 | unsigned long tmp; | ||
277 | |||
278 | regs = task_pt_regs(child); | ||
279 | |||
280 | tmp = 0; /* Default return value. */ | ||
281 | switch (addr) { | ||
282 | case 0 ... 31: | ||
283 | tmp = regs->regs[addr]; | ||
284 | break; | ||
285 | case PC: | ||
286 | tmp = regs->cp0_epc; | ||
287 | break; | ||
288 | case ECR: | ||
289 | tmp = regs->cp0_ecr; | ||
290 | break; | ||
291 | case EMA: | ||
292 | tmp = regs->cp0_ema; | ||
293 | break; | ||
294 | case CEH: | ||
295 | tmp = regs->ceh; | ||
296 | break; | ||
297 | case CEL: | ||
298 | tmp = regs->cel; | ||
299 | break; | ||
300 | case CONDITION: | ||
301 | tmp = regs->cp0_condition; | ||
302 | break; | ||
303 | case PSR: | ||
304 | tmp = regs->cp0_psr; | ||
305 | break; | ||
306 | case COUNTER: | ||
307 | tmp = regs->sr0; | ||
308 | break; | ||
309 | case LDCR: | ||
310 | tmp = regs->sr1; | ||
311 | break; | ||
312 | case STCR: | ||
313 | tmp = regs->sr2; | ||
314 | break; | ||
315 | default: | ||
316 | tmp = 0; | ||
317 | return -EIO; | ||
318 | } | ||
319 | |||
320 | ret = put_user(tmp, (unsigned int __user *) datap); | ||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | case PTRACE_POKEUSR: { | ||
325 | struct pt_regs *regs; | ||
326 | ret = 0; | ||
327 | regs = task_pt_regs(child); | ||
328 | |||
329 | switch (addr) { | ||
330 | case 0 ... 31: | ||
331 | regs->regs[addr] = data; | ||
332 | break; | ||
333 | case PC: | ||
334 | regs->cp0_epc = data; | ||
335 | break; | ||
336 | case CEH: | ||
337 | regs->ceh = data; | ||
338 | break; | ||
339 | case CEL: | ||
340 | regs->cel = data; | ||
341 | break; | ||
342 | case CONDITION: | ||
343 | regs->cp0_condition = data; | ||
344 | break; | ||
345 | case PSR: | ||
346 | case COUNTER: | ||
347 | case STCR: | ||
348 | case LDCR: | ||
349 | break; /* user can't write the reg */ | ||
350 | default: | ||
351 | /* The rest are not allowed. */ | ||
352 | ret = -EIO; | ||
353 | break; | ||
354 | } | ||
355 | break; | ||
356 | } | ||
357 | |||
358 | case PTRACE_GETREGS: | 334 | case PTRACE_GETREGS: |
359 | ret = ptrace_getregs(child, (void __user *)datap); | 335 | ret = copy_regset_to_user(child, &user_score_native_view, |
336 | REGSET_GENERAL, | ||
337 | 0, sizeof(struct pt_regs), | ||
338 | (void __user *)datap); | ||
360 | break; | 339 | break; |
361 | 340 | ||
362 | case PTRACE_SETREGS: | 341 | case PTRACE_SETREGS: |
363 | ret = ptrace_setregs(child, (void __user *)datap); | 342 | ret = copy_regset_from_user(child, &user_score_native_view, |
343 | REGSET_GENERAL, | ||
344 | 0, sizeof(struct pt_regs), | ||
345 | (const void __user *)datap); | ||
364 | break; | 346 | break; |
365 | 347 | ||
366 | default: | 348 | default: |