aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/ptrace.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-06-04 01:15:41 -0400
committerPaul Mackerras <paulus@samba.org>2007-06-14 08:29:56 -0400
commitacd89828484db6371202f5d292781ae6f832eda2 (patch)
treedff9b004db1d108ece5154b708b273723907d041 /arch/powerpc/kernel/ptrace.c
parent0b3d5c48a98f7bd2d38962f5a67b480ac5656fb9 (diff)
[POWERPC] ptrace cleanups
The powerpc ptrace code has some weirdness, like a ptrace-common.h file that is actually ppc64 only and some of the 32 bits code ifdef'ed inside ptrace.c. There are also separate implementations for things like get/set_vrregs for 32 and 64 bits which is totally unnecessary. This patch cleans that up a bit by having a ptrace-common.h which contains really common code (and makes a lot more code common), and ptrace-ppc32.h and ptrace-ppc64.h files that contain the few remaining different bits. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/ptrace.c')
-rw-r--r--arch/powerpc/kernel/ptrace.c198
1 files changed, 4 insertions, 194 deletions
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 36db6f5cb54c..da53b0d4114b 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -36,208 +36,18 @@
36#include <asm/system.h> 36#include <asm/system.h>
37 37
38#ifdef CONFIG_PPC64 38#ifdef CONFIG_PPC64
39#include "ptrace-common.h" 39#include "ptrace-ppc64.h"
40#endif
41
42#ifdef CONFIG_PPC32
43/*
44 * Set of msr bits that gdb can change on behalf of a process.
45 */
46#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
47#define MSR_DEBUGCHANGE 0
48#else 40#else
49#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) 41#include "ptrace-ppc32.h"
50#endif 42#endif
51#endif /* CONFIG_PPC32 */ 43
44#include "ptrace-common.h"
52 45
53/* 46/*
54 * does not yet catch signals sent when the child dies. 47 * does not yet catch signals sent when the child dies.
55 * in exit.c or in signal.c. 48 * in exit.c or in signal.c.
56 */ 49 */
57 50
58#ifdef CONFIG_PPC32
59/*
60 * Get contents of register REGNO in task TASK.
61 */
62static inline unsigned long get_reg(struct task_struct *task, int regno)
63{
64 if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
65 && task->thread.regs != NULL)
66 return ((unsigned long *)task->thread.regs)[regno];
67 return (0);
68}
69
70/*
71 * Write contents of register REGNO in task TASK.
72 */
73static inline int put_reg(struct task_struct *task, int regno,
74 unsigned long data)
75{
76 if (regno <= PT_MQ && task->thread.regs != NULL) {
77 if (regno == PT_MSR)
78 data = (data & MSR_DEBUGCHANGE)
79 | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
80 ((unsigned long *)task->thread.regs)[regno] = data;
81 return 0;
82 }
83 return -EIO;
84}
85
86#ifdef CONFIG_ALTIVEC
87/*
88 * Get contents of AltiVec register state in task TASK
89 */
90static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
91{
92 int i, j;
93
94 if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
95 return -EFAULT;
96
97 /* copy AltiVec registers VR[0] .. VR[31] */
98 for (i = 0; i < 32; i++)
99 for (j = 0; j < 4; j++, data++)
100 if (__put_user(task->thread.vr[i].u[j], data))
101 return -EFAULT;
102
103 /* copy VSCR */
104 for (i = 0; i < 4; i++, data++)
105 if (__put_user(task->thread.vscr.u[i], data))
106 return -EFAULT;
107
108 /* copy VRSAVE */
109 if (__put_user(task->thread.vrsave, data))
110 return -EFAULT;
111
112 return 0;
113}
114
115/*
116 * Write contents of AltiVec register state into task TASK.
117 */
118static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
119{
120 int i, j;
121
122 if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
123 return -EFAULT;
124
125 /* copy AltiVec registers VR[0] .. VR[31] */
126 for (i = 0; i < 32; i++)
127 for (j = 0; j < 4; j++, data++)
128 if (__get_user(task->thread.vr[i].u[j], data))
129 return -EFAULT;
130
131 /* copy VSCR */
132 for (i = 0; i < 4; i++, data++)
133 if (__get_user(task->thread.vscr.u[i], data))
134 return -EFAULT;
135
136 /* copy VRSAVE */
137 if (__get_user(task->thread.vrsave, data))
138 return -EFAULT;
139
140 return 0;
141}
142#endif
143
144#ifdef CONFIG_SPE
145
146/*
147 * For get_evrregs/set_evrregs functions 'data' has the following layout:
148 *
149 * struct {
150 * u32 evr[32];
151 * u64 acc;
152 * u32 spefscr;
153 * }
154 */
155
156/*
157 * Get contents of SPE register state in task TASK.
158 */
159static inline int get_evrregs(unsigned long *data, struct task_struct *task)
160{
161 int i;
162
163 if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long)))
164 return -EFAULT;
165
166 /* copy SPEFSCR */
167 if (__put_user(task->thread.spefscr, &data[34]))
168 return -EFAULT;
169
170 /* copy SPE registers EVR[0] .. EVR[31] */
171 for (i = 0; i < 32; i++, data++)
172 if (__put_user(task->thread.evr[i], data))
173 return -EFAULT;
174
175 /* copy ACC */
176 if (__put_user64(task->thread.acc, (unsigned long long *)data))
177 return -EFAULT;
178
179 return 0;
180}
181
182/*
183 * Write contents of SPE register state into task TASK.
184 */
185static inline int set_evrregs(struct task_struct *task, unsigned long *data)
186{
187 int i;
188
189 if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long)))
190 return -EFAULT;
191
192 /* copy SPEFSCR */
193 if (__get_user(task->thread.spefscr, &data[34]))
194 return -EFAULT;
195
196 /* copy SPE registers EVR[0] .. EVR[31] */
197 for (i = 0; i < 32; i++, data++)
198 if (__get_user(task->thread.evr[i], data))
199 return -EFAULT;
200 /* copy ACC */
201 if (__get_user64(task->thread.acc, (unsigned long long*)data))
202 return -EFAULT;
203
204 return 0;
205}
206#endif /* CONFIG_SPE */
207
208static inline void
209set_single_step(struct task_struct *task)
210{
211 struct pt_regs *regs = task->thread.regs;
212
213 if (regs != NULL) {
214#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
215 task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
216 regs->msr |= MSR_DE;
217#else
218 regs->msr |= MSR_SE;
219#endif
220 }
221 set_tsk_thread_flag(task, TIF_SINGLESTEP);
222}
223
224static inline void
225clear_single_step(struct task_struct *task)
226{
227 struct pt_regs *regs = task->thread.regs;
228
229 if (regs != NULL) {
230#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
231 task->thread.dbcr0 = 0;
232 regs->msr &= ~MSR_DE;
233#else
234 regs->msr &= ~MSR_SE;
235#endif
236 }
237 clear_tsk_thread_flag(task, TIF_SINGLESTEP);
238}
239#endif /* CONFIG_PPC32 */
240
241/* 51/*
242 * Called by kernel/ptrace.c when detaching.. 52 * Called by kernel/ptrace.c when detaching..
243 * 53 *