~ubuntu-branches/ubuntu/precise/linux-linaro-u8500/precise

« back to all changes in this revision

Viewing changes to arch/arm/kernel/ptrace.c

  • Committer: Bazaar Package Importer
  • Author(s): John Rigby, Upstream Fixes, Andy Green, John Rigby
  • Date: 2011-04-14 12:16:06 UTC
  • Revision ID: james.westby@ubuntu.com-20110414121606-b77podkyqgr2oix7
Tags: 2.6.38-1002.3
[ Upstream Fixes ]

* MUSB: shutdown: Make sure block is awake before doing shutdown
  - LP: #745737
* Fixed gpio polarity of gpio USB-phy reset.
  - LP: #747639

[ Andy Green ]

* LINARO: SAUCE: disable CONFIG_OMAP_RESET_CLOCKS
  - LP: #752900

[ John Rigby ]

* Rebase to new upstreams:
  Linux v2.6.38.1
  linaro-linux-2.6.38-upstream-29Mar2011
  Ubuntu-2.6.38-7.35
* SAUCE: OMAP4: clock: wait for module to become accessible on
  a clk enable
  - LP: #745737
* Rebase to new upstreams:
  Linux v2.6.38.2
  linaro-linux-2.6.38-upstream-5Apr2011
  Ubuntu-2.6.38-8.41
  - LP: #732842
* Update configs for device tree, dvfs and lttng
* LINARO: add building of dtb's
* LINARO: SAUCE: Disable lowest operating freqs on omap34xx
  - LP: #732912

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include <linux/uaccess.h>
22
22
#include <linux/perf_event.h>
23
23
#include <linux/hw_breakpoint.h>
 
24
#include <linux/module.h>
 
25
#include <linux/marker.h>
 
26
#include <linux/kallsyms.h>
 
27
#include <trace/syscall.h>
 
28
#include <linux/regset.h>
24
29
 
25
30
#include <asm/pgtable.h>
26
31
#include <asm/system.h>
27
32
#include <asm/traps.h>
 
33
#include <asm/unistd.h>
28
34
 
29
35
#define REG_PC  15
30
36
#define REG_PSR 16
52
58
#define BREAKINST_THUMB 0xde01
53
59
#endif
54
60
 
 
61
DEFINE_TRACE(syscall_entry);
 
62
DEFINE_TRACE(syscall_exit);
 
63
 
 
64
extern unsigned long sys_call_table[];
 
65
 
 
66
void ltt_dump_sys_call_table(void *call_data)
 
67
{
 
68
        int i;
 
69
        char namebuf[KSYM_NAME_LEN];
 
70
 
 
71
        for (i = 0; i < __NR_syscall_max + 1; i++) {
 
72
                sprint_symbol(namebuf, sys_call_table[i]);
 
73
                __trace_mark(0, syscall_state, sys_call_table, call_data,
 
74
                        "id %d address %p symbol %s",
 
75
                        i, (void*)sys_call_table[i], namebuf);
 
76
        }
 
77
}
 
78
EXPORT_SYMBOL_GPL(ltt_dump_sys_call_table);
 
79
 
 
80
void ltt_dump_idt_table(void *call_data)
 
81
{
 
82
}
 
83
EXPORT_SYMBOL_GPL(ltt_dump_idt_table);
 
84
 
55
85
struct pt_regs_offset {
56
86
        const char *name;
57
87
        int offset;
308
338
        return put_user_reg(tsk, off >> 2, val);
309
339
}
310
340
 
311
 
/*
312
 
 * Get all user integer registers.
313
 
 */
314
 
static int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
315
 
{
316
 
        struct pt_regs *regs = task_pt_regs(tsk);
317
 
 
318
 
        return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
319
 
}
320
 
 
321
 
/*
322
 
 * Set all user integer registers.
323
 
 */
324
 
static int ptrace_setregs(struct task_struct *tsk, void __user *uregs)
325
 
{
326
 
        struct pt_regs newregs;
327
 
        int ret;
328
 
 
329
 
        ret = -EFAULT;
330
 
        if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
331
 
                struct pt_regs *regs = task_pt_regs(tsk);
332
 
 
333
 
                ret = -EINVAL;
334
 
                if (valid_user_regs(&newregs)) {
335
 
                        *regs = newregs;
336
 
                        ret = 0;
337
 
                }
338
 
        }
339
 
 
340
 
        return ret;
341
 
}
342
 
 
343
 
/*
344
 
 * Get the child FPU state.
345
 
 */
346
 
static int ptrace_getfpregs(struct task_struct *tsk, void __user *ufp)
347
 
{
348
 
        return copy_to_user(ufp, &task_thread_info(tsk)->fpstate,
349
 
                            sizeof(struct user_fp)) ? -EFAULT : 0;
350
 
}
351
 
 
352
 
/*
353
 
 * Set the child FPU state.
354
 
 */
355
 
static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp)
356
 
{
357
 
        struct thread_info *thread = task_thread_info(tsk);
358
 
        thread->used_cp[1] = thread->used_cp[2] = 1;
359
 
        return copy_from_user(&thread->fpstate, ufp,
360
 
                              sizeof(struct user_fp)) ? -EFAULT : 0;
361
 
}
362
 
 
363
341
#ifdef CONFIG_IWMMXT
364
342
 
365
343
/*
418
396
}
419
397
#endif
420
398
 
421
 
#ifdef CONFIG_VFP
422
 
/*
423
 
 * Get the child VFP state.
424
 
 */
425
 
static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)
426
 
{
427
 
        struct thread_info *thread = task_thread_info(tsk);
428
 
        union vfp_state *vfp = &thread->vfpstate;
429
 
        struct user_vfp __user *ufp = data;
430
 
 
431
 
        vfp_sync_hwstate(thread);
432
 
 
433
 
        /* copy the floating point registers */
434
 
        if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs,
435
 
                         sizeof(vfp->hard.fpregs)))
436
 
                return -EFAULT;
437
 
 
438
 
        /* copy the status and control register */
439
 
        if (put_user(vfp->hard.fpscr, &ufp->fpscr))
440
 
                return -EFAULT;
441
 
 
442
 
        return 0;
443
 
}
444
 
 
445
 
/*
446
 
 * Set the child VFP state.
447
 
 */
448
 
static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
449
 
{
450
 
        struct thread_info *thread = task_thread_info(tsk);
451
 
        union vfp_state *vfp = &thread->vfpstate;
452
 
        struct user_vfp __user *ufp = data;
453
 
 
454
 
        vfp_sync_hwstate(thread);
455
 
 
456
 
        /* copy the floating point registers */
457
 
        if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs,
458
 
                           sizeof(vfp->hard.fpregs)))
459
 
                return -EFAULT;
460
 
 
461
 
        /* copy the status and control register */
462
 
        if (get_user(vfp->hard.fpscr, &ufp->fpscr))
463
 
                return -EFAULT;
464
 
 
465
 
        vfp_flush_hwstate(thread);
466
 
 
467
 
        return 0;
468
 
}
469
 
#endif
470
 
 
471
399
#ifdef CONFIG_HAVE_HW_BREAKPOINT
472
400
/*
473
401
 * Convert a virtual register number into an index for a thread_info
694
622
}
695
623
#endif
696
624
 
 
625
/* regset get/set implementations */
 
626
 
 
627
static int gpr_get(struct task_struct *target,
 
628
                   const struct user_regset *regset,
 
629
                   unsigned int pos, unsigned int count,
 
630
                   void *kbuf, void __user *ubuf)
 
631
{
 
632
        struct pt_regs *regs = task_pt_regs(target);
 
633
 
 
634
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 
635
                                   regs,
 
636
                                   0, sizeof(*regs));
 
637
}
 
638
 
 
639
static int gpr_set(struct task_struct *target,
 
640
                   const struct user_regset *regset,
 
641
                   unsigned int pos, unsigned int count,
 
642
                   const void *kbuf, const void __user *ubuf)
 
643
{
 
644
        int ret;
 
645
        struct pt_regs newregs;
 
646
 
 
647
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 
648
                                 &newregs,
 
649
                                 0, sizeof(newregs));
 
650
        if (ret)
 
651
                return ret;
 
652
 
 
653
        if (!valid_user_regs(&newregs))
 
654
                return -EINVAL;
 
655
 
 
656
        *task_pt_regs(target) = newregs;
 
657
        return 0;
 
658
}
 
659
 
 
660
static int fpa_get(struct task_struct *target,
 
661
                   const struct user_regset *regset,
 
662
                   unsigned int pos, unsigned int count,
 
663
                   void *kbuf, void __user *ubuf)
 
664
{
 
665
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 
666
                                   &task_thread_info(target)->fpstate,
 
667
                                   0, sizeof(struct user_fp));
 
668
}
 
669
 
 
670
static int fpa_set(struct task_struct *target,
 
671
                   const struct user_regset *regset,
 
672
                   unsigned int pos, unsigned int count,
 
673
                   const void *kbuf, const void __user *ubuf)
 
674
{
 
675
        struct thread_info *thread = task_thread_info(target);
 
676
 
 
677
        thread->used_cp[1] = thread->used_cp[2] = 1;
 
678
 
 
679
        return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 
680
                &thread->fpstate,
 
681
                0, sizeof(struct user_fp));
 
682
}
 
683
 
 
684
#ifdef CONFIG_VFP
 
685
/*
 
686
 * VFP register get/set implementations.
 
687
 *
 
688
 * With respect to the kernel, struct user_fp is divided into three chunks:
 
689
 * 16 or 32 real VFP registers (d0-d15 or d0-31)
 
690
 *      These are transferred to/from the real registers in the task's
 
691
 *      vfp_hard_struct.  The number of registers depends on the kernel
 
692
 *      configuration.
 
693
 *
 
694
 * 16 or 0 fake VFP registers (d16-d31 or empty)
 
695
 *      i.e., the user_vfp structure has space for 32 registers even if
 
696
 *      the kernel doesn't have them all.
 
697
 *
 
698
 *      vfp_get() reads this chunk as zero where applicable
 
699
 *      vfp_set() ignores this chunk
 
700
 *
 
701
 * 1 word for the FPSCR
 
702
 *
 
703
 * The bounds-checking logic built into user_regset_copyout and friends
 
704
 * means that we can make a simple sequence of calls to map the relevant data
 
705
 * to/from the specified slice of the user regset structure.
 
706
 */
 
707
static int vfp_get(struct task_struct *target,
 
708
                   const struct user_regset *regset,
 
709
                   unsigned int pos, unsigned int count,
 
710
                   void *kbuf, void __user *ubuf)
 
711
{
 
712
        int ret;
 
713
        struct thread_info *thread = task_thread_info(target);
 
714
        struct vfp_hard_struct const *vfp = &thread->vfpstate.hard;
 
715
        const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
 
716
        const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
 
717
 
 
718
        vfp_sync_hwstate(thread);
 
719
 
 
720
        ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 
721
                                  &vfp->fpregs,
 
722
                                  user_fpregs_offset,
 
723
                                  user_fpregs_offset + sizeof(vfp->fpregs));
 
724
        if (ret)
 
725
                return ret;
 
726
 
 
727
        ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 
728
                                       user_fpregs_offset + sizeof(vfp->fpregs),
 
729
                                       user_fpscr_offset);
 
730
        if (ret)
 
731
                return ret;
 
732
 
 
733
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 
734
                                   &vfp->fpscr,
 
735
                                   user_fpscr_offset,
 
736
                                   user_fpscr_offset + sizeof(vfp->fpscr));
 
737
}
 
738
 
 
739
/*
 
740
 * For vfp_set() a read-modify-write is done on the VFP registers,
 
741
 * in order to avoid writing back a half-modified set of registers on
 
742
 * failure.
 
743
 */
 
744
static int vfp_set(struct task_struct *target,
 
745
                          const struct user_regset *regset,
 
746
                          unsigned int pos, unsigned int count,
 
747
                          const void *kbuf, const void __user *ubuf)
 
748
{
 
749
        int ret;
 
750
        struct thread_info *thread = task_thread_info(target);
 
751
        struct vfp_hard_struct new_vfp = thread->vfpstate.hard;
 
752
        const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
 
753
        const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
 
754
 
 
755
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 
756
                                  &new_vfp.fpregs,
 
757
                                  user_fpregs_offset,
 
758
                                  user_fpregs_offset + sizeof(new_vfp.fpregs));
 
759
        if (ret)
 
760
                return ret;
 
761
 
 
762
        ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 
763
                                user_fpregs_offset + sizeof(new_vfp.fpregs),
 
764
                                user_fpscr_offset);
 
765
        if (ret)
 
766
                return ret;
 
767
 
 
768
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 
769
                                 &new_vfp.fpscr,
 
770
                                 user_fpscr_offset,
 
771
                                 user_fpscr_offset + sizeof(new_vfp.fpscr));
 
772
        if (ret)
 
773
                return ret;
 
774
 
 
775
        vfp_sync_hwstate(thread);
 
776
        thread->vfpstate.hard = new_vfp;
 
777
        vfp_flush_hwstate(thread);
 
778
 
 
779
        return 0;
 
780
}
 
781
#endif /* CONFIG_VFP */
 
782
 
 
783
enum arm_regset {
 
784
        REGSET_GPR,
 
785
        REGSET_FPR,
 
786
#ifdef CONFIG_VFP
 
787
        REGSET_VFP,
 
788
#endif
 
789
};
 
790
 
 
791
static const struct user_regset arm_regsets[] = {
 
792
        [REGSET_GPR] = {
 
793
                .core_note_type = NT_PRSTATUS,
 
794
                .n = ELF_NGREG,
 
795
                .size = sizeof(u32),
 
796
                .align = sizeof(u32),
 
797
                .get = gpr_get,
 
798
                .set = gpr_set
 
799
        },
 
800
        [REGSET_FPR] = {
 
801
                /*
 
802
                 * For the FPA regs in fpstate, the real fields are a mixture
 
803
                 * of sizes, so pretend that the registers are word-sized:
 
804
                 */
 
805
                .core_note_type = NT_PRFPREG,
 
806
                .n = sizeof(struct user_fp) / sizeof(u32),
 
807
                .size = sizeof(u32),
 
808
                .align = sizeof(u32),
 
809
                .get = fpa_get,
 
810
                .set = fpa_set
 
811
        },
 
812
#ifdef CONFIG_VFP
 
813
        [REGSET_VFP] = {
 
814
                /*
 
815
                 * Pretend that the VFP regs are word-sized, since the FPSCR is
 
816
                 * a single word dangling at the end of struct user_vfp:
 
817
                 */
 
818
                .core_note_type = NT_ARM_VFP,
 
819
                .n = ARM_VFPREGS_SIZE / sizeof(u32),
 
820
                .size = sizeof(u32),
 
821
                .align = sizeof(u32),
 
822
                .get = vfp_get,
 
823
                .set = vfp_set
 
824
        },
 
825
#endif /* CONFIG_VFP */
 
826
};
 
827
 
 
828
static const struct user_regset_view user_arm_view = {
 
829
        .name = "arm", .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI,
 
830
        .regsets = arm_regsets, .n = ARRAY_SIZE(arm_regsets)
 
831
};
 
832
 
 
833
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 
834
{
 
835
        return &user_arm_view;
 
836
}
 
837
 
697
838
long arch_ptrace(struct task_struct *child, long request,
698
839
                 unsigned long addr, unsigned long data)
699
840
{
710
851
                        break;
711
852
 
712
853
                case PTRACE_GETREGS:
713
 
                        ret = ptrace_getregs(child, datap);
 
854
                        ret = copy_regset_to_user(child,
 
855
                                                  &user_arm_view, REGSET_GPR,
 
856
                                                  0, sizeof(struct pt_regs),
 
857
                                                  datap);
714
858
                        break;
715
859
 
716
860
                case PTRACE_SETREGS:
717
 
                        ret = ptrace_setregs(child, datap);
 
861
                        ret = copy_regset_from_user(child,
 
862
                                                    &user_arm_view, REGSET_GPR,
 
863
                                                    0, sizeof(struct pt_regs),
 
864
                                                    datap);
718
865
                        break;
719
866
 
720
867
                case PTRACE_GETFPREGS:
721
 
                        ret = ptrace_getfpregs(child, datap);
 
868
                        ret = copy_regset_to_user(child,
 
869
                                                  &user_arm_view, REGSET_FPR,
 
870
                                                  0, sizeof(union fp_state),
 
871
                                                  datap);
722
872
                        break;
723
 
                
 
873
 
724
874
                case PTRACE_SETFPREGS:
725
 
                        ret = ptrace_setfpregs(child, datap);
 
875
                        ret = copy_regset_from_user(child,
 
876
                                                    &user_arm_view, REGSET_FPR,
 
877
                                                    0, sizeof(union fp_state),
 
878
                                                    datap);
726
879
                        break;
727
880
 
728
881
#ifdef CONFIG_IWMMXT
757
910
 
758
911
#ifdef CONFIG_VFP
759
912
                case PTRACE_GETVFPREGS:
760
 
                        ret = ptrace_getvfpregs(child, datap);
 
913
                        ret = copy_regset_to_user(child,
 
914
                                                  &user_arm_view, REGSET_VFP,
 
915
                                                  0, ARM_VFPREGS_SIZE,
 
916
                                                  datap);
761
917
                        break;
762
918
 
763
919
                case PTRACE_SETVFPREGS:
764
 
                        ret = ptrace_setvfpregs(child, datap);
 
920
                        ret = copy_regset_from_user(child,
 
921
                                                    &user_arm_view, REGSET_VFP,
 
922
                                                    0, ARM_VFPREGS_SIZE,
 
923
                                                    datap);
765
924
                        break;
766
925
#endif
767
926
 
788
947
{
789
948
        unsigned long ip;
790
949
 
 
950
        if (!why)
 
951
                trace_syscall_entry(regs, scno);
 
952
        else
 
953
                trace_syscall_exit(regs->ARM_r0);
 
954
 
791
955
        if (!test_thread_flag(TIF_SYSCALL_TRACE))
792
956
                return scno;
793
957
        if (!(current->ptrace & PT_PTRACED))