aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile')
-rw-r--r--arch/tile/kernel/compat.c4
-rw-r--r--arch/tile/kernel/ptrace.c78
2 files changed, 38 insertions, 44 deletions
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c
index 5f24e54bf3c5..77739cdd9462 100644
--- a/arch/tile/kernel/compat.c
+++ b/arch/tile/kernel/compat.c
@@ -154,8 +154,8 @@ long tile_compat_sys_msgrcv(int msqid,
154#define compat_sys_fstat64 sys_newfstat 154#define compat_sys_fstat64 sys_newfstat
155#define compat_sys_fstatat64 sys_newfstatat 155#define compat_sys_fstatat64 sys_newfstatat
156 156
157/* Pass full 64-bit values through ptrace. */ 157/* The native sys_ptrace dynamically handles compat binaries. */
158#define compat_sys_ptrace tile_compat_sys_ptrace 158#define compat_sys_ptrace sys_ptrace
159 159
160/* Call the trampolines to manage pt_regs where necessary. */ 160/* Call the trampolines to manage pt_regs where necessary. */
161#define compat_sys_execve _compat_sys_execve 161#define compat_sys_execve _compat_sys_execve
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c
index 7161bd03d2fd..5b20c2874d51 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)
@@ -66,59 +47,72 @@ void ptrace_disable(struct task_struct *child)
66 47
67long arch_ptrace(struct task_struct *child, long request, long addr, long data) 48long arch_ptrace(struct task_struct *child, long request, long addr, long data)
68{ 49{
69 unsigned long __user *datap; 50 unsigned long __user *datap = (long __user __force *)data;
70 unsigned long tmp; 51 unsigned long tmp;
71 int i; 52 int i;
72 long ret = -EIO; 53 long ret = -EIO;
73 54 unsigned long *childregs;
74#ifdef CONFIG_COMPAT 55 char *childreg;
75 if (task_thread_info(current)->status & TS_COMPAT)
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 56
82 switch (request) { 57 switch (request) {
83 58
84 case PTRACE_PEEKUSR: /* Read register from pt_regs. */ 59 case PTRACE_PEEKUSR: /* Read register from pt_regs. */
85 if (addr & (sizeof(data)-1))
86 break;
87 if (addr < 0 || addr >= PTREGS_SIZE) 60 if (addr < 0 || addr >= PTREGS_SIZE)
88 break; 61 break;
89 tmp = getreg(child, addr); /* Read register */ 62 childreg = (char *)task_pt_regs(child) + addr;
90 ret = put_user(tmp, datap); 63#ifdef CONFIG_COMPAT
64 if (is_compat_task()) {
65 if (addr & (sizeof(compat_long_t)-1))
66 break;
67 ret = put_user(*(compat_long_t *)childreg,
68 (compat_long_t __user *)datap);
69 } else
70#endif
71 {
72 if (addr & (sizeof(long)-1))
73 break;
74 ret = put_user(*(long *)childreg, datap);
75 }
91 break; 76 break;
92 77
93 case PTRACE_POKEUSR: /* Write register in pt_regs. */ 78 case PTRACE_POKEUSR: /* Write register in pt_regs. */
94 if (addr & (sizeof(data)-1))
95 break;
96 if (addr < 0 || addr >= PTREGS_SIZE) 79 if (addr < 0 || addr >= PTREGS_SIZE)
97 break; 80 break;
98 putreg(child, addr, data); /* Write register */ 81 childreg = (char *)task_pt_regs(child) + addr;
82#ifdef CONFIG_COMPAT
83 if (is_compat_task()) {
84 if (addr & (sizeof(compat_long_t)-1))
85 break;
86 *(compat_long_t *)childreg = data;
87 } else
88#endif
89 {
90 if (addr & (sizeof(long)-1))
91 break;
92 *(long *)childreg = data;
93 }
99 ret = 0; 94 ret = 0;
100 break; 95 break;
101 96
102 case PTRACE_GETREGS: /* Get all registers from the child. */ 97 case PTRACE_GETREGS: /* Get all registers from the child. */
103 if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE)) 98 if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE))
104 break; 99 break;
105 for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) { 100 childregs = (long *)task_pt_regs(child);
106 ret = __put_user(getreg(child, i), datap); 101 for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) {
102 ret = __put_user(childregs[i], &datap[i]);
107 if (ret != 0) 103 if (ret != 0)
108 break; 104 break;
109 datap++;
110 } 105 }
111 break; 106 break;
112 107
113 case PTRACE_SETREGS: /* Set all registers in the child. */ 108 case PTRACE_SETREGS: /* Set all registers in the child. */
114 if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE)) 109 if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE))
115 break; 110 break;
116 for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) { 111 childregs = (long *)task_pt_regs(child);
117 ret = __get_user(tmp, datap); 112 for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) {
113 ret = __get_user(childregs[i], &datap[i]);
118 if (ret != 0) 114 if (ret != 0)
119 break; 115 break;
120 putreg(child, i, tmp);
121 datap++;
122 } 116 }
123 break; 117 break;
124 118