diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-06-04 01:15:47 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-06-14 08:29:57 -0400 |
commit | abd0650541604d6c028bcbf5002e4a68aaf56e90 (patch) | |
tree | a915cecfa86f34ea8a2661d311548da009379c21 | |
parent | 912000e73ee8fcb97831b123c9c3a7274b71cab7 (diff) |
[POWERPC] ptrace shouldn't touch FP exec mode
One of the gratuitous difference between 32 and 64-bit ptrace is
whether you can whack the MSR:FE0 and FE1 bits from ptrace. This
patch forbids it unconditionally. In addition, the 64-bit kernels
used to return the exception mode in the MSR on reads, but 32-bit
kernels didn't. This patch makes it return those bits on both.
Finally, since ptrace-ppc32.h and ptrace-ppc64.h are mostly empty now, and
since the previous patch made ptrace32.c no longer need the MSR_DEBUGCHANGE
definition, we just remove those 2 files and move back the remaining bits
to ptrace.c (they were short lived heh ?).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/kernel/ptrace-ppc32.h | 35 | ||||
-rw-r--r-- | arch/powerpc/kernel/ptrace-ppc64.h | 51 | ||||
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 45 | ||||
-rw-r--r-- | arch/powerpc/kernel/ptrace32.c | 2 |
4 files changed, 39 insertions, 94 deletions
diff --git a/arch/powerpc/kernel/ptrace-ppc32.h b/arch/powerpc/kernel/ptrace-ppc32.h deleted file mode 100644 index f1fd5b8a868d..000000000000 --- a/arch/powerpc/kernel/ptrace-ppc32.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration | ||
3 | * Extracted from ptrace.c and ptrace32.c | ||
4 | * | ||
5 | * This file is subject to the terms and conditions of the GNU General | ||
6 | * Public License. See the file README.legal in the main directory of | ||
7 | * this archive for more details. | ||
8 | */ | ||
9 | |||
10 | #ifndef _POWERPC_PTRACE_PPC32_H | ||
11 | #define _POWERPC_PTRACE_PPC32_H | ||
12 | |||
13 | /* | ||
14 | * Set of msr bits that gdb can change on behalf of a process. | ||
15 | */ | ||
16 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | ||
17 | #define MSR_DEBUGCHANGE 0 | ||
18 | #else | ||
19 | #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) | ||
20 | #endif | ||
21 | |||
22 | /* | ||
23 | * Max register writeable via put_reg | ||
24 | */ | ||
25 | #define PT_MAX_PUT_REG PT_MQ | ||
26 | |||
27 | /* | ||
28 | * Munging of MSR on return from get_regs | ||
29 | * | ||
30 | * Nothing to do on ppc32 | ||
31 | */ | ||
32 | #define PT_MUNGE_MSR(msr, task) (msr) | ||
33 | |||
34 | |||
35 | #endif /* _POWERPC_PTRACE_PPC32_H */ | ||
diff --git a/arch/powerpc/kernel/ptrace-ppc64.h b/arch/powerpc/kernel/ptrace-ppc64.h deleted file mode 100644 index e450ce01392b..000000000000 --- a/arch/powerpc/kernel/ptrace-ppc64.h +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2002 Stephen Rothwell, IBM Coproration | ||
3 | * Extracted from ptrace.c and ptrace32.c | ||
4 | * | ||
5 | * This file is subject to the terms and conditions of the GNU General | ||
6 | * Public License. See the file README.legal in the main directory of | ||
7 | * this archive for more details. | ||
8 | */ | ||
9 | |||
10 | #ifndef _POWERPC_PTRACE_PPC64_H | ||
11 | #define _POWERPC_PTRACE_PPC64_H | ||
12 | |||
13 | /* | ||
14 | * Set of msr bits that gdb can change on behalf of a process. | ||
15 | */ | ||
16 | #define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1) | ||
17 | |||
18 | /* | ||
19 | * Max register writeable via put_reg | ||
20 | */ | ||
21 | #define PT_MAX_PUT_REG PT_CCR | ||
22 | |||
23 | /* | ||
24 | * Munging of MSR on return from get_regs | ||
25 | * | ||
26 | * Put the correct FP bits in, they might be wrong as a result | ||
27 | * of our lazy FP restore. | ||
28 | */ | ||
29 | |||
30 | #define PT_MUNGE_MSR(msr, task) ({ (msr) | (task)->thread.fpexc_mode; }) | ||
31 | |||
32 | static inline int ptrace_set_debugreg(struct task_struct *task, | ||
33 | unsigned long addr, unsigned long data) | ||
34 | { | ||
35 | /* We only support one DABR and no IABRS at the moment */ | ||
36 | if (addr > 0) | ||
37 | return -EINVAL; | ||
38 | |||
39 | /* The bottom 3 bits are flags */ | ||
40 | if ((data & ~0x7UL) >= TASK_SIZE) | ||
41 | return -EIO; | ||
42 | |||
43 | /* Ensure translation is on */ | ||
44 | if (data && !(data & DABR_TRANSLATION)) | ||
45 | return -EIO; | ||
46 | |||
47 | task->thread.dabr = data; | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | #endif /* _POWERPC_PTRACE_PPC64_H */ | ||
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index dd4837c4a68a..75bc744a6217 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -35,16 +35,28 @@ | |||
35 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
36 | #include <asm/system.h> | 36 | #include <asm/system.h> |
37 | 37 | ||
38 | #ifdef CONFIG_PPC64 | 38 | /* |
39 | #include "ptrace-ppc64.h" | 39 | * does not yet catch signals sent when the child dies. |
40 | * in exit.c or in signal.c. | ||
41 | */ | ||
42 | |||
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 | ||
40 | #else | 48 | #else |
41 | #include "ptrace-ppc32.h" | 49 | #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) |
42 | #endif | 50 | #endif |
43 | 51 | ||
44 | /* | 52 | /* |
45 | * does not yet catch signals sent when the child dies. | 53 | * Max register writeable via put_reg |
46 | * in exit.c or in signal.c. | ||
47 | */ | 54 | */ |
55 | #ifdef CONFIG_PPC32 | ||
56 | #define PT_MAX_PUT_REG PT_MQ | ||
57 | #else | ||
58 | #define PT_MAX_PUT_REG PT_CCR | ||
59 | #endif | ||
48 | 60 | ||
49 | /* | 61 | /* |
50 | * Get contents of register REGNO in task TASK. | 62 | * Get contents of register REGNO in task TASK. |
@@ -58,7 +70,7 @@ unsigned long ptrace_get_reg(struct task_struct *task, int regno) | |||
58 | 70 | ||
59 | if (regno == PT_MSR) { | 71 | if (regno == PT_MSR) { |
60 | tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; | 72 | tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; |
61 | return PT_MUNGE_MSR(tmp, task); | 73 | return tmp | task->thread.fpexc_mode; |
62 | } | 74 | } |
63 | 75 | ||
64 | if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) | 76 | if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) |
@@ -274,6 +286,27 @@ static void clear_single_step(struct task_struct *task) | |||
274 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); | 286 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); |
275 | } | 287 | } |
276 | 288 | ||
289 | #ifdef CONFIG_PPC64 | ||
290 | static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | ||
291 | unsigned long data) | ||
292 | { | ||
293 | /* We only support one DABR and no IABRS at the moment */ | ||
294 | if (addr > 0) | ||
295 | return -EINVAL; | ||
296 | |||
297 | /* The bottom 3 bits are flags */ | ||
298 | if ((data & ~0x7UL) >= TASK_SIZE) | ||
299 | return -EIO; | ||
300 | |||
301 | /* Ensure translation is on */ | ||
302 | if (data && !(data & DABR_TRANSLATION)) | ||
303 | return -EIO; | ||
304 | |||
305 | task->thread.dabr = data; | ||
306 | return 0; | ||
307 | } | ||
308 | #endif | ||
309 | |||
277 | /* | 310 | /* |
278 | * Called by kernel/ptrace.c when detaching.. | 311 | * Called by kernel/ptrace.c when detaching.. |
279 | * | 312 | * |
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index aae6a988e183..9e6baeac0fb1 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
@@ -33,8 +33,6 @@ | |||
33 | #include <asm/pgtable.h> | 33 | #include <asm/pgtable.h> |
34 | #include <asm/system.h> | 34 | #include <asm/system.h> |
35 | 35 | ||
36 | #include "ptrace-ppc64.h" | ||
37 | |||
38 | /* | 36 | /* |
39 | * does not yet catch signals sent when the child dies. | 37 | * does not yet catch signals sent when the child dies. |
40 | * in exit.c or in signal.c. | 38 | * in exit.c or in signal.c. |