aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-06-04 01:15:44 -0400
committerPaul Mackerras <paulus@samba.org>2007-06-14 08:29:57 -0400
commit865418d8e78b9c11c964157740b2596d6ffe9dfa (patch)
tree2ef4b1652fe38c7b9e172ca7a8aef906602d3692 /arch
parente17666ba48f78ff10162d7448e7c92d668d8faf6 (diff)
[POWERPC] Uninline common ptrace bits
This folds back the ptrace-common.h bits back into ptrace.c and removes that file. The FSL SPE bits from ptrace-ppc32.h are folded back in as well. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/ptrace-common.h177
-rw-r--r--arch/powerpc/kernel/ptrace-ppc32.h65
-rw-r--r--arch/powerpc/kernel/ptrace.c233
-rw-r--r--arch/powerpc/kernel/ptrace32.c11
4 files changed, 232 insertions, 254 deletions
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h
deleted file mode 100644
index 21884535fee6..000000000000
--- a/arch/powerpc/kernel/ptrace-common.h
+++ /dev/null
@@ -1,177 +0,0 @@
1/*
2 * Copyright (c) 2002 Stephen Rothwell, IBM Coproration
3 * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
4 * Extracted from ptrace.c and ptrace32.c
5 *
6 * This file is subject to the terms and conditions of the GNU General
7 * Public License. See the file README.legal in the main directory of
8 * this archive for more details.
9 */
10
11#ifndef _POWERPC_PTRACE_COMMON_H
12#define _POWERPC_PTRACE_COMMON_H
13
14/*
15 * Get contents of register REGNO in task TASK.
16 */
17static inline unsigned long get_reg(struct task_struct *task, int regno)
18{
19 unsigned long tmp = 0;
20
21 if (task->thread.regs == NULL)
22 return -EIO;
23
24 if (regno == PT_MSR) {
25 tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
26 return PT_MUNGE_MSR(tmp, task);
27 }
28
29 if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
30 return ((unsigned long *)task->thread.regs)[regno];
31
32 return -EIO;
33}
34
35/*
36 * Write contents of register REGNO in task TASK.
37 */
38static inline int put_reg(struct task_struct *task, int regno,
39 unsigned long data)
40{
41 if (task->thread.regs == NULL)
42 return -EIO;
43
44 if (regno <= PT_MAX_PUT_REG) {
45 if (regno == PT_MSR)
46 data = (data & MSR_DEBUGCHANGE)
47 | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
48 ((unsigned long *)task->thread.regs)[regno] = data;
49 return 0;
50 }
51 return -EIO;
52}
53
54
55static inline int get_fpregs(void __user *data,
56 struct task_struct *task,
57 int has_fpscr)
58{
59 unsigned int count = has_fpscr ? 33 : 32;
60
61 if (copy_to_user(data, task->thread.fpr, count * sizeof(double)))
62 return -EFAULT;
63 return 0;
64}
65
66static inline int set_fpregs(void __user *data,
67 struct task_struct *task,
68 int has_fpscr)
69{
70 unsigned int count = has_fpscr ? 33 : 32;
71
72 if (copy_from_user(task->thread.fpr, data, count * sizeof(double)))
73 return -EFAULT;
74 return 0;
75}
76
77
78#ifdef CONFIG_ALTIVEC
79/*
80 * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
81 * The transfer totals 34 quadword. Quadwords 0-31 contain the
82 * corresponding vector registers. Quadword 32 contains the vscr as the
83 * last word (offset 12) within that quadword. Quadword 33 contains the
84 * vrsave as the first word (offset 0) within the quadword.
85 *
86 * This definition of the VMX state is compatible with the current PPC32
87 * ptrace interface. This allows signal handling and ptrace to use the
88 * same structures. This also simplifies the implementation of a bi-arch
89 * (combined (32- and 64-bit) gdb.
90 */
91
92/*
93 * Get contents of AltiVec register state in task TASK
94 */
95static inline int get_vrregs(unsigned long __user *data,
96 struct task_struct *task)
97{
98 unsigned long regsize;
99
100 /* copy AltiVec registers VR[0] .. VR[31] */
101 regsize = 32 * sizeof(vector128);
102 if (copy_to_user(data, task->thread.vr, regsize))
103 return -EFAULT;
104 data += (regsize / sizeof(unsigned long));
105
106 /* copy VSCR */
107 regsize = 1 * sizeof(vector128);
108 if (copy_to_user(data, &task->thread.vscr, regsize))
109 return -EFAULT;
110 data += (regsize / sizeof(unsigned long));
111
112 /* copy VRSAVE */
113 if (put_user(task->thread.vrsave, (u32 __user *)data))
114 return -EFAULT;
115
116 return 0;
117}
118
119/*
120 * Write contents of AltiVec register state into task TASK.
121 */
122static inline int set_vrregs(struct task_struct *task,
123 unsigned long __user *data)
124{
125 unsigned long regsize;
126
127 /* copy AltiVec registers VR[0] .. VR[31] */
128 regsize = 32 * sizeof(vector128);
129 if (copy_from_user(task->thread.vr, data, regsize))
130 return -EFAULT;
131 data += (regsize / sizeof(unsigned long));
132
133 /* copy VSCR */
134 regsize = 1 * sizeof(vector128);
135 if (copy_from_user(&task->thread.vscr, data, regsize))
136 return -EFAULT;
137 data += (regsize / sizeof(unsigned long));
138
139 /* copy VRSAVE */
140 if (get_user(task->thread.vrsave, (u32 __user *)data))
141 return -EFAULT;
142
143 return 0;
144}
145#endif /* CONFIG_ALTIVEC */
146
147static inline void set_single_step(struct task_struct *task)
148{
149 struct pt_regs *regs = task->thread.regs;
150
151 if (regs != NULL) {
152#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
153 task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
154 regs->msr |= MSR_DE;
155#else
156 regs->msr |= MSR_SE;
157#endif
158 }
159 set_tsk_thread_flag(task, TIF_SINGLESTEP);
160}
161
162static inline void clear_single_step(struct task_struct *task)
163{
164 struct pt_regs *regs = task->thread.regs;
165
166 if (regs != NULL) {
167#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
168 task->thread.dbcr0 = 0;
169 regs->msr &= ~MSR_DE;
170#else
171 regs->msr &= ~MSR_SE;
172#endif
173 }
174 clear_tsk_thread_flag(task, TIF_SINGLESTEP);
175}
176
177#endif /* _POWERPC_PTRACE_COMMON_H */
diff --git a/arch/powerpc/kernel/ptrace-ppc32.h b/arch/powerpc/kernel/ptrace-ppc32.h
index 24d7a2f680af..f1fd5b8a868d 100644
--- a/arch/powerpc/kernel/ptrace-ppc32.h
+++ b/arch/powerpc/kernel/ptrace-ppc32.h
@@ -32,69 +32,4 @@
32#define PT_MUNGE_MSR(msr, task) (msr) 32#define PT_MUNGE_MSR(msr, task) (msr)
33 33
34 34
35#ifdef CONFIG_SPE
36
37/*
38 * For get_evrregs/set_evrregs functions 'data' has the following layout:
39 *
40 * struct {
41 * u32 evr[32];
42 * u64 acc;
43 * u32 spefscr;
44 * }
45 */
46
47/*
48 * Get contents of SPE register state in task TASK.
49 */
50static inline int get_evrregs(unsigned long *data, struct task_struct *task)
51{
52 int i;
53
54 if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long)))
55 return -EFAULT;
56
57 /* copy SPEFSCR */
58 if (__put_user(task->thread.spefscr, &data[34]))
59 return -EFAULT;
60
61 /* copy SPE registers EVR[0] .. EVR[31] */
62 for (i = 0; i < 32; i++, data++)
63 if (__put_user(task->thread.evr[i], data))
64 return -EFAULT;
65
66 /* copy ACC */
67 if (__put_user64(task->thread.acc, (unsigned long long *)data))
68 return -EFAULT;
69
70 return 0;
71}
72
73/*
74 * Write contents of SPE register state into task TASK.
75 */
76static inline int set_evrregs(struct task_struct *task, unsigned long *data)
77{
78 int i;
79
80 if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long)))
81 return -EFAULT;
82
83 /* copy SPEFSCR */
84 if (__get_user(task->thread.spefscr, &data[34]))
85 return -EFAULT;
86
87 /* copy SPE registers EVR[0] .. EVR[31] */
88 for (i = 0; i < 32; i++, data++)
89 if (__get_user(task->thread.evr[i], data))
90 return -EFAULT;
91 /* copy ACC */
92 if (__get_user64(task->thread.acc, (unsigned long long*)data))
93 return -EFAULT;
94
95 return 0;
96}
97#endif /* CONFIG_SPE */
98
99
100#endif /* _POWERPC_PTRACE_PPC32_H */ 35#endif /* _POWERPC_PTRACE_PPC32_H */
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 230d5f5bfab6..875bfda90b21 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -41,14 +41,235 @@
41#include "ptrace-ppc32.h" 41#include "ptrace-ppc32.h"
42#endif 42#endif
43 43
44#include "ptrace-common.h"
45
46/* 44/*
47 * does not yet catch signals sent when the child dies. 45 * does not yet catch signals sent when the child dies.
48 * in exit.c or in signal.c. 46 * in exit.c or in signal.c.
49 */ 47 */
50 48
51/* 49/*
50 * Get contents of register REGNO in task TASK.
51 */
52unsigned long ptrace_get_reg(struct task_struct *task, int regno)
53{
54 unsigned long tmp = 0;
55
56 if (task->thread.regs == NULL)
57 return -EIO;
58
59 if (regno == PT_MSR) {
60 tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
61 return PT_MUNGE_MSR(tmp, task);
62 }
63
64 if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
65 return ((unsigned long *)task->thread.regs)[regno];
66
67 return -EIO;
68}
69
70/*
71 * Write contents of register REGNO in task TASK.
72 */
73int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
74{
75 if (task->thread.regs == NULL)
76 return -EIO;
77
78 if (regno <= PT_MAX_PUT_REG) {
79 if (regno == PT_MSR)
80 data = (data & MSR_DEBUGCHANGE)
81 | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
82 ((unsigned long *)task->thread.regs)[regno] = data;
83 return 0;
84 }
85 return -EIO;
86}
87
88
89static int get_fpregs(void __user *data, struct task_struct *task,
90 int has_fpscr)
91{
92 unsigned int count = has_fpscr ? 33 : 32;
93
94 if (copy_to_user(data, task->thread.fpr, count * sizeof(double)))
95 return -EFAULT;
96 return 0;
97}
98
99static int set_fpregs(void __user *data, struct task_struct *task,
100 int has_fpscr)
101{
102 unsigned int count = has_fpscr ? 33 : 32;
103
104 if (copy_from_user(task->thread.fpr, data, count * sizeof(double)))
105 return -EFAULT;
106 return 0;
107}
108
109
110#ifdef CONFIG_ALTIVEC
111/*
112 * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
113 * The transfer totals 34 quadword. Quadwords 0-31 contain the
114 * corresponding vector registers. Quadword 32 contains the vscr as the
115 * last word (offset 12) within that quadword. Quadword 33 contains the
116 * vrsave as the first word (offset 0) within the quadword.
117 *
118 * This definition of the VMX state is compatible with the current PPC32
119 * ptrace interface. This allows signal handling and ptrace to use the
120 * same structures. This also simplifies the implementation of a bi-arch
121 * (combined (32- and 64-bit) gdb.
122 */
123
124/*
125 * Get contents of AltiVec register state in task TASK
126 */
127static int get_vrregs(unsigned long __user *data, struct task_struct *task)
128{
129 unsigned long regsize;
130
131 /* copy AltiVec registers VR[0] .. VR[31] */
132 regsize = 32 * sizeof(vector128);
133 if (copy_to_user(data, task->thread.vr, regsize))
134 return -EFAULT;
135 data += (regsize / sizeof(unsigned long));
136
137 /* copy VSCR */
138 regsize = 1 * sizeof(vector128);
139 if (copy_to_user(data, &task->thread.vscr, regsize))
140 return -EFAULT;
141 data += (regsize / sizeof(unsigned long));
142
143 /* copy VRSAVE */
144 if (put_user(task->thread.vrsave, (u32 __user *)data))
145 return -EFAULT;
146
147 return 0;
148}
149
150/*
151 * Write contents of AltiVec register state into task TASK.
152 */
153static int set_vrregs(struct task_struct *task, unsigned long __user *data)
154{
155 unsigned long regsize;
156
157 /* copy AltiVec registers VR[0] .. VR[31] */
158 regsize = 32 * sizeof(vector128);
159 if (copy_from_user(task->thread.vr, data, regsize))
160 return -EFAULT;
161 data += (regsize / sizeof(unsigned long));
162
163 /* copy VSCR */
164 regsize = 1 * sizeof(vector128);
165 if (copy_from_user(&task->thread.vscr, data, regsize))
166 return -EFAULT;
167 data += (regsize / sizeof(unsigned long));
168
169 /* copy VRSAVE */
170 if (get_user(task->thread.vrsave, (u32 __user *)data))
171 return -EFAULT;
172
173 return 0;
174}
175#endif /* CONFIG_ALTIVEC */
176
177#ifdef CONFIG_SPE
178
179/*
180 * For get_evrregs/set_evrregs functions 'data' has the following layout:
181 *
182 * struct {
183 * u32 evr[32];
184 * u64 acc;
185 * u32 spefscr;
186 * }
187 */
188
189/*
190 * Get contents of SPE register state in task TASK.
191 */
192static int get_evrregs(unsigned long *data, struct task_struct *task)
193{
194 int i;
195
196 if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long)))
197 return -EFAULT;
198
199 /* copy SPEFSCR */
200 if (__put_user(task->thread.spefscr, &data[34]))
201 return -EFAULT;
202
203 /* copy SPE registers EVR[0] .. EVR[31] */
204 for (i = 0; i < 32; i++, data++)
205 if (__put_user(task->thread.evr[i], data))
206 return -EFAULT;
207
208 /* copy ACC */
209 if (__put_user64(task->thread.acc, (unsigned long long *)data))
210 return -EFAULT;
211
212 return 0;
213}
214
215/*
216 * Write contents of SPE register state into task TASK.
217 */
218static int set_evrregs(struct task_struct *task, unsigned long *data)
219{
220 int i;
221
222 if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long)))
223 return -EFAULT;
224
225 /* copy SPEFSCR */
226 if (__get_user(task->thread.spefscr, &data[34]))
227 return -EFAULT;
228
229 /* copy SPE registers EVR[0] .. EVR[31] */
230 for (i = 0; i < 32; i++, data++)
231 if (__get_user(task->thread.evr[i], data))
232 return -EFAULT;
233 /* copy ACC */
234 if (__get_user64(task->thread.acc, (unsigned long long*)data))
235 return -EFAULT;
236
237 return 0;
238}
239#endif /* CONFIG_SPE */
240
241
242static void set_single_step(struct task_struct *task)
243{
244 struct pt_regs *regs = task->thread.regs;
245
246 if (regs != NULL) {
247#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
248 task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
249 regs->msr |= MSR_DE;
250#else
251 regs->msr |= MSR_SE;
252#endif
253 }
254 set_tsk_thread_flag(task, TIF_SINGLESTEP);
255}
256
257static void clear_single_step(struct task_struct *task)
258{
259 struct pt_regs *regs = task->thread.regs;
260
261 if (regs != NULL) {
262#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
263 task->thread.dbcr0 = 0;
264 regs->msr &= ~MSR_DE;
265#else
266 regs->msr &= ~MSR_SE;
267#endif
268 }
269 clear_tsk_thread_flag(task, TIF_SINGLESTEP);
270}
271
272/*
52 * Called by kernel/ptrace.c when detaching.. 273 * Called by kernel/ptrace.c when detaching..
53 * 274 *
54 * Make sure single step bits etc are not set. 275 * Make sure single step bits etc are not set.
@@ -154,7 +375,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
154 CHECK_FULL_REGS(child->thread.regs); 375 CHECK_FULL_REGS(child->thread.regs);
155#endif 376#endif
156 if (index < PT_FPR0) { 377 if (index < PT_FPR0) {
157 tmp = get_reg(child, (int) index); 378 tmp = ptrace_get_reg(child, (int) index);
158 } else { 379 } else {
159 flush_fp_to_thread(child); 380 flush_fp_to_thread(child);
160 tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; 381 tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
@@ -195,7 +416,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
195 if (index == PT_ORIG_R3) 416 if (index == PT_ORIG_R3)
196 break; 417 break;
197 if (index < PT_FPR0) { 418 if (index < PT_FPR0) {
198 ret = put_reg(child, index, data); 419 ret = ptrace_put_reg(child, index, data);
199 } else { 420 } else {
200 flush_fp_to_thread(child); 421 flush_fp_to_thread(child);
201 ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; 422 ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
@@ -282,7 +503,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
282 } 503 }
283 ret = 0; 504 ret = 0;
284 for (ui = 0; ui < PT_REGS_COUNT; ui ++) { 505 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
285 ret |= __put_user(get_reg(child, ui), 506 ret |= __put_user(ptrace_get_reg(child, ui),
286 (unsigned long __user *) data); 507 (unsigned long __user *) data);
287 data += sizeof(long); 508 data += sizeof(long);
288 } 509 }
@@ -305,7 +526,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
305 ret = __get_user(tmp, (unsigned long __user *) data); 526 ret = __get_user(tmp, (unsigned long __user *) data);
306 if (ret) 527 if (ret)
307 break; 528 break;
308 put_reg(child, ui, tmp); 529 ptrace_put_reg(child, ui, tmp);
309 data += sizeof(long); 530 data += sizeof(long);
310 } 531 }
311 break; 532 break;
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 98b1580a2bc2..4511b422992f 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -34,7 +34,6 @@
34#include <asm/system.h> 34#include <asm/system.h>
35 35
36#include "ptrace-ppc64.h" 36#include "ptrace-ppc64.h"
37#include "ptrace-common.h"
38 37
39/* 38/*
40 * does not yet catch signals sent when the child dies. 39 * does not yet catch signals sent when the child dies.
@@ -168,7 +167,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
168 break; 167 break;
169 168
170 if (index < PT_FPR0) { 169 if (index < PT_FPR0) {
171 tmp = get_reg(child, index); 170 tmp = ptrace_get_reg(child, index);
172 } else { 171 } else {
173 flush_fp_to_thread(child); 172 flush_fp_to_thread(child);
174 /* 173 /*
@@ -215,7 +214,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
215 flush_fp_to_thread(child); 214 flush_fp_to_thread(child);
216 tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0]; 215 tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
217 } else { /* register within PT_REGS struct */ 216 } else { /* register within PT_REGS struct */
218 tmp = get_reg(child, numReg); 217 tmp = ptrace_get_reg(child, numReg);
219 } 218 }
220 reg32bits = ((u32*)&tmp)[part]; 219 reg32bits = ((u32*)&tmp)[part];
221 ret = put_user(reg32bits, (u32 __user *)data); 220 ret = put_user(reg32bits, (u32 __user *)data);
@@ -274,7 +273,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
274 if (index == PT_ORIG_R3) 273 if (index == PT_ORIG_R3)
275 break; 274 break;
276 if (index < PT_FPR0) { 275 if (index < PT_FPR0) {
277 ret = put_reg(child, index, data); 276 ret = ptrace_put_reg(child, index, data);
278 } else { 277 } else {
279 flush_fp_to_thread(child); 278 flush_fp_to_thread(child);
280 /* 279 /*
@@ -346,7 +345,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
346 } 345 }
347 ret = 0; 346 ret = 0;
348 for (ui = 0; ui < PT_REGS_COUNT; ui ++) { 347 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
349 ret |= __put_user(get_reg(child, ui), 348 ret |= __put_user(ptrace_get_reg(child, ui),
350 (unsigned int __user *) data); 349 (unsigned int __user *) data);
351 data += sizeof(int); 350 data += sizeof(int);
352 } 351 }
@@ -366,7 +365,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
366 ret = __get_user(tmp, (unsigned int __user *) data); 365 ret = __get_user(tmp, (unsigned int __user *) data);
367 if (ret) 366 if (ret)
368 break; 367 break;
369 put_reg(child, ui, tmp); 368 ptrace_put_reg(child, ui, tmp);
370 data += sizeof(int); 369 data += sizeof(int);
371 } 370 }
372 break; 371 break;