aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel/ptrace.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/tile/kernel/ptrace.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'arch/tile/kernel/ptrace.c')
-rw-r--r--arch/tile/kernel/ptrace.c108
1 files changed, 54 insertions, 54 deletions
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c
index 7161bd03d2fd..e92e40527d6d 100644
--- a/arch/tile/kernel/ptrace.c
+++ b/arch/tile/kernel/ptrace.c
@@ -32,25 +32,6 @@ void user_disable_single_step(struct task_struct *child)
32} 32}
33 33
34/* 34/*
35 * This routine will put a word on the process's privileged stack.
36 */
37static void putreg(struct task_struct *task,
38 unsigned long addr, unsigned long value)
39{
40 unsigned int regno = addr / sizeof(unsigned long);
41 struct pt_regs *childregs = task_pt_regs(task);
42 childregs->regs[regno] = value;
43 childregs->flags |= PT_FLAGS_RESTORE_REGS;
44}
45
46static unsigned long getreg(struct task_struct *task, unsigned long addr)
47{
48 unsigned int regno = addr / sizeof(unsigned long);
49 struct pt_regs *childregs = task_pt_regs(task);
50 return childregs->regs[regno];
51}
52
53/*
54 * Called by kernel/ptrace.c when detaching.. 35 * Called by kernel/ptrace.c when detaching..
55 */ 36 */
56void ptrace_disable(struct task_struct *child) 37void ptrace_disable(struct task_struct *child)
@@ -64,61 +45,80 @@ void ptrace_disable(struct task_struct *child)
64 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 45 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
65} 46}
66 47
67long arch_ptrace(struct task_struct *child, long request, long addr, long data) 48long arch_ptrace(struct task_struct *child, long request,
49 unsigned long addr, unsigned long data)
68{ 50{
69 unsigned long __user *datap; 51 unsigned long __user *datap = (long __user __force *)data;
70 unsigned long tmp; 52 unsigned long tmp;
71 int i;
72 long ret = -EIO; 53 long ret = -EIO;
73 54 char *childreg;
74#ifdef CONFIG_COMPAT 55 struct pt_regs copyregs;
75 if (task_thread_info(current)->status & TS_COMPAT) 56 int ex1_offset;
76 data = (u32)data;
77 if (task_thread_info(child)->status & TS_COMPAT)
78 addr = (u32)addr;
79#endif
80 datap = (unsigned long __user __force *)data;
81 57
82 switch (request) { 58 switch (request) {
83 59
84 case PTRACE_PEEKUSR: /* Read register from pt_regs. */ 60 case PTRACE_PEEKUSR: /* Read register from pt_regs. */
85 if (addr & (sizeof(data)-1)) 61 if (addr >= PTREGS_SIZE)
86 break;
87 if (addr < 0 || addr >= PTREGS_SIZE)
88 break; 62 break;
89 tmp = getreg(child, addr); /* Read register */ 63 childreg = (char *)task_pt_regs(child) + addr;
90 ret = put_user(tmp, datap); 64#ifdef CONFIG_COMPAT
65 if (is_compat_task()) {
66 if (addr & (sizeof(compat_long_t)-1))
67 break;
68 ret = put_user(*(compat_long_t *)childreg,
69 (compat_long_t __user *)datap);
70 } else
71#endif
72 {
73 if (addr & (sizeof(long)-1))
74 break;
75 ret = put_user(*(long *)childreg, datap);
76 }
91 break; 77 break;
92 78
93 case PTRACE_POKEUSR: /* Write register in pt_regs. */ 79 case PTRACE_POKEUSR: /* Write register in pt_regs. */
94 if (addr & (sizeof(data)-1)) 80 if (addr >= PTREGS_SIZE)
95 break; 81 break;
96 if (addr < 0 || addr >= PTREGS_SIZE) 82 childreg = (char *)task_pt_regs(child) + addr;
97 break; 83
98 putreg(child, addr, data); /* Write register */ 84 /* Guard against overwrites of the privilege level. */
85 ex1_offset = PTREGS_OFFSET_EX1;
86#if defined(CONFIG_COMPAT) && defined(__BIG_ENDIAN)
87 if (is_compat_task()) /* point at low word */
88 ex1_offset += sizeof(compat_long_t);
89#endif
90 if (addr == ex1_offset)
91 data = PL_ICS_EX1(USER_PL, EX1_ICS(data));
92
93#ifdef CONFIG_COMPAT
94 if (is_compat_task()) {
95 if (addr & (sizeof(compat_long_t)-1))
96 break;
97 *(compat_long_t *)childreg = data;
98 } else
99#endif
100 {
101 if (addr & (sizeof(long)-1))
102 break;
103 *(long *)childreg = data;
104 }
99 ret = 0; 105 ret = 0;
100 break; 106 break;
101 107
102 case PTRACE_GETREGS: /* Get all registers from the child. */ 108 case PTRACE_GETREGS: /* Get all registers from the child. */
103 if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE)) 109 if (copy_to_user(datap, task_pt_regs(child),
104 break; 110 sizeof(struct pt_regs)) == 0) {
105 for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) { 111 ret = 0;
106 ret = __put_user(getreg(child, i), datap);
107 if (ret != 0)
108 break;
109 datap++;
110 } 112 }
111 break; 113 break;
112 114
113 case PTRACE_SETREGS: /* Set all registers in the child. */ 115 case PTRACE_SETREGS: /* Set all registers in the child. */
114 if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE)) 116 if (copy_from_user(&copyregs, datap,
115 break; 117 sizeof(struct pt_regs)) == 0) {
116 for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) { 118 copyregs.ex1 =
117 ret = __get_user(tmp, datap); 119 PL_ICS_EX1(USER_PL, EX1_ICS(copyregs.ex1));
118 if (ret != 0) 120 *task_pt_regs(child) = copyregs;
119 break; 121 ret = 0;
120 putreg(child, i, tmp);
121 datap++;
122 } 122 }
123 break; 123 break;
124 124