aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/ptrace.c')
-rw-r--r--arch/arm/kernel/ptrace.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index a2ea3854cb3c..08f899fb76a6 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -499,10 +499,41 @@ static struct undef_hook thumb_break_hook = {
499 .fn = break_trap, 499 .fn = break_trap,
500}; 500};
501 501
502static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr)
503{
504 unsigned int instr2;
505 void __user *pc;
506
507 /* Check the second half of the instruction. */
508 pc = (void __user *)(instruction_pointer(regs) + 2);
509
510 if (processor_mode(regs) == SVC_MODE) {
511 instr2 = *(u16 *) pc;
512 } else {
513 get_user(instr2, (u16 __user *)pc);
514 }
515
516 if (instr2 == 0xa000) {
517 ptrace_break(current, regs);
518 return 0;
519 } else {
520 return 1;
521 }
522}
523
524static struct undef_hook thumb2_break_hook = {
525 .instr_mask = 0xffff,
526 .instr_val = 0xf7f0,
527 .cpsr_mask = PSR_T_BIT,
528 .cpsr_val = PSR_T_BIT,
529 .fn = thumb2_break_trap,
530};
531
502static int __init ptrace_break_init(void) 532static int __init ptrace_break_init(void)
503{ 533{
504 register_undef_hook(&arm_break_hook); 534 register_undef_hook(&arm_break_hook);
505 register_undef_hook(&thumb_break_hook); 535 register_undef_hook(&thumb_break_hook);
536 register_undef_hook(&thumb2_break_hook);
506 return 0; 537 return 0;
507} 538}
508 539
@@ -669,7 +700,7 @@ static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)
669 union vfp_state *vfp = &thread->vfpstate; 700 union vfp_state *vfp = &thread->vfpstate;
670 struct user_vfp __user *ufp = data; 701 struct user_vfp __user *ufp = data;
671 702
672 vfp_sync_state(thread); 703 vfp_sync_hwstate(thread);
673 704
674 /* copy the floating point registers */ 705 /* copy the floating point registers */
675 if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs, 706 if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs,
@@ -692,7 +723,7 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
692 union vfp_state *vfp = &thread->vfpstate; 723 union vfp_state *vfp = &thread->vfpstate;
693 struct user_vfp __user *ufp = data; 724 struct user_vfp __user *ufp = data;
694 725
695 vfp_sync_state(thread); 726 vfp_sync_hwstate(thread);
696 727
697 /* copy the floating point registers */ 728 /* copy the floating point registers */
698 if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs, 729 if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs,
@@ -703,6 +734,8 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
703 if (get_user(vfp->hard.fpscr, &ufp->fpscr)) 734 if (get_user(vfp->hard.fpscr, &ufp->fpscr))
704 return -EFAULT; 735 return -EFAULT;
705 736
737 vfp_flush_hwstate(thread);
738
706 return 0; 739 return 0;
707} 740}
708#endif 741#endif
@@ -712,26 +745,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
712 int ret; 745 int ret;
713 746
714 switch (request) { 747 switch (request) {
715 /*
716 * read word at location "addr" in the child process.
717 */
718 case PTRACE_PEEKTEXT:
719 case PTRACE_PEEKDATA:
720 ret = generic_ptrace_peekdata(child, addr, data);
721 break;
722
723 case PTRACE_PEEKUSR: 748 case PTRACE_PEEKUSR:
724 ret = ptrace_read_user(child, addr, (unsigned long __user *)data); 749 ret = ptrace_read_user(child, addr, (unsigned long __user *)data);
725 break; 750 break;
726 751
727 /*
728 * write the word at location addr.
729 */
730 case PTRACE_POKETEXT:
731 case PTRACE_POKEDATA:
732 ret = generic_ptrace_pokedata(child, addr, data);
733 break;
734
735 case PTRACE_POKEUSR: 752 case PTRACE_POKEUSR:
736 ret = ptrace_write_user(child, addr, data); 753 ret = ptrace_write_user(child, addr, data);
737 break; 754 break;