diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2012-08-02 08:44:11 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-10-29 16:25:05 -0400 |
commit | 7aeb753b53538bc3b4377022db7aa3ae42653ce3 (patch) | |
tree | 464dbe488772b2a4d19a52e069cedb78eee740fb /arch | |
parent | bc3d22c13e8b1ae0be016c67406787231f9e6548 (diff) |
MIPS: Implement task_user_regset_view.
There are no users yet of task_user_regset_view. yet; users will be
implemented rsp activated in subsequent commits.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/kernel/ptrace.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 7a5d7ac6b0d4..83a6a464db70 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -16,11 +16,13 @@ | |||
16 | */ | 16 | */ |
17 | #include <linux/compiler.h> | 17 | #include <linux/compiler.h> |
18 | #include <linux/context_tracking.h> | 18 | #include <linux/context_tracking.h> |
19 | #include <linux/elf.h> | ||
19 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
20 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
21 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
22 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
23 | #include <linux/ptrace.h> | 24 | #include <linux/ptrace.h> |
25 | #include <linux/regset.h> | ||
24 | #include <linux/smp.h> | 26 | #include <linux/smp.h> |
25 | #include <linux/user.h> | 27 | #include <linux/user.h> |
26 | #include <linux/security.h> | 28 | #include <linux/security.h> |
@@ -256,6 +258,133 @@ int ptrace_set_watch_regs(struct task_struct *child, | |||
256 | return 0; | 258 | return 0; |
257 | } | 259 | } |
258 | 260 | ||
261 | /* regset get/set implementations */ | ||
262 | |||
263 | static int gpr_get(struct task_struct *target, | ||
264 | const struct user_regset *regset, | ||
265 | unsigned int pos, unsigned int count, | ||
266 | void *kbuf, void __user *ubuf) | ||
267 | { | ||
268 | struct pt_regs *regs = task_pt_regs(target); | ||
269 | |||
270 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
271 | regs, 0, sizeof(*regs)); | ||
272 | } | ||
273 | |||
274 | static int gpr_set(struct task_struct *target, | ||
275 | const struct user_regset *regset, | ||
276 | unsigned int pos, unsigned int count, | ||
277 | const void *kbuf, const void __user *ubuf) | ||
278 | { | ||
279 | struct pt_regs newregs; | ||
280 | int ret; | ||
281 | |||
282 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
283 | &newregs, | ||
284 | 0, sizeof(newregs)); | ||
285 | if (ret) | ||
286 | return ret; | ||
287 | |||
288 | *task_pt_regs(target) = newregs; | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int fpr_get(struct task_struct *target, | ||
294 | const struct user_regset *regset, | ||
295 | unsigned int pos, unsigned int count, | ||
296 | void *kbuf, void __user *ubuf) | ||
297 | { | ||
298 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
299 | &target->thread.fpu, | ||
300 | 0, sizeof(elf_fpregset_t)); | ||
301 | /* XXX fcr31 */ | ||
302 | } | ||
303 | |||
304 | static int fpr_set(struct task_struct *target, | ||
305 | const struct user_regset *regset, | ||
306 | unsigned int pos, unsigned int count, | ||
307 | const void *kbuf, const void __user *ubuf) | ||
308 | { | ||
309 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
310 | &target->thread.fpu, | ||
311 | 0, sizeof(elf_fpregset_t)); | ||
312 | /* XXX fcr31 */ | ||
313 | } | ||
314 | |||
315 | enum mips_regset { | ||
316 | REGSET_GPR, | ||
317 | REGSET_FPR, | ||
318 | }; | ||
319 | |||
320 | static const struct user_regset mips_regsets[] = { | ||
321 | [REGSET_GPR] = { | ||
322 | .core_note_type = NT_PRSTATUS, | ||
323 | .n = ELF_NGREG, | ||
324 | .size = sizeof(unsigned int), | ||
325 | .align = sizeof(unsigned int), | ||
326 | .get = gpr_get, | ||
327 | .set = gpr_set, | ||
328 | }, | ||
329 | [REGSET_FPR] = { | ||
330 | .core_note_type = NT_PRFPREG, | ||
331 | .n = ELF_NFPREG, | ||
332 | .size = sizeof(elf_fpreg_t), | ||
333 | .align = sizeof(elf_fpreg_t), | ||
334 | .get = fpr_get, | ||
335 | .set = fpr_set, | ||
336 | }, | ||
337 | }; | ||
338 | |||
339 | static const struct user_regset_view user_mips_view = { | ||
340 | .name = "mips", | ||
341 | .e_machine = ELF_ARCH, | ||
342 | .ei_osabi = ELF_OSABI, | ||
343 | .regsets = mips_regsets, | ||
344 | .n = ARRAY_SIZE(mips_regsets), | ||
345 | }; | ||
346 | |||
347 | static const struct user_regset mips64_regsets[] = { | ||
348 | [REGSET_GPR] = { | ||
349 | .core_note_type = NT_PRSTATUS, | ||
350 | .n = ELF_NGREG, | ||
351 | .size = sizeof(unsigned long), | ||
352 | .align = sizeof(unsigned long), | ||
353 | .get = gpr_get, | ||
354 | .set = gpr_set, | ||
355 | }, | ||
356 | [REGSET_FPR] = { | ||
357 | .core_note_type = NT_PRFPREG, | ||
358 | .n = ELF_NFPREG, | ||
359 | .size = sizeof(elf_fpreg_t), | ||
360 | .align = sizeof(elf_fpreg_t), | ||
361 | .get = fpr_get, | ||
362 | .set = fpr_set, | ||
363 | }, | ||
364 | }; | ||
365 | |||
366 | static const struct user_regset_view user_mips64_view = { | ||
367 | .name = "mips", | ||
368 | .e_machine = ELF_ARCH, | ||
369 | .ei_osabi = ELF_OSABI, | ||
370 | .regsets = mips64_regsets, | ||
371 | .n = ARRAY_SIZE(mips_regsets), | ||
372 | }; | ||
373 | |||
374 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) | ||
375 | { | ||
376 | #ifdef CONFIG_32BIT | ||
377 | return &user_mips_view; | ||
378 | #endif | ||
379 | |||
380 | #ifdef CONFIG_MIPS32_O32 | ||
381 | if (test_thread_flag(TIF_32BIT_REGS)) | ||
382 | return &user_mips_view; | ||
383 | #endif | ||
384 | |||
385 | return &user_mips64_view; | ||
386 | } | ||
387 | |||
259 | long arch_ptrace(struct task_struct *child, long request, | 388 | long arch_ptrace(struct task_struct *child, long request, |
260 | unsigned long addr, unsigned long data) | 389 | unsigned long addr, unsigned long data) |
261 | { | 390 | { |