]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Michael Neuling <mikey@neuling.org> |
2 | Subject: powerpc: Fix ptrace compat wrapper for FPU register access | |
3 | Patch-mainline: 2.6.30-rc4 | |
4 | Git-commit: bc826666e4252f78d2b144af3b7d699ff5efce0a | |
5 | References: bnc#496027 | |
6 | ||
7 | powerpc: Fix ptrace compat wrapper for FPU register access | |
8 | ||
9 | The ptrace compat wrapper mishandles access to the fpu registers. The | |
10 | PTRACE_PEEKUSR and PTRACE_POKEUSR requests miscalculate the index into | |
11 | the fpr array due to the broken FPINDEX macro. The | |
12 | PPC_PTRACE_PEEKUSR_3264 request needs to use the same formula that the | |
13 | native ptrace interface uses when operating on the register number (as | |
14 | opposed to the 4-byte offset). The PPC_PTRACE_POKEUSR_3264 request | |
15 | didn't take TS_FPRWIDTH into account. | |
16 | ||
17 | Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> | |
18 | Signed-off-by: Michael Neuling <mikey@neuling.org> | |
19 | Signed-off-by: Paul Mackerras <paulus@samba.org> | |
20 | Acked-by: Jeff Mahoney <jeffm@suse.com> | |
21 | --- | |
22 | arch/powerpc/kernel/ptrace32.c | 15 +++++++++++---- | |
23 | 1 file changed, 11 insertions(+), 4 deletions(-) | |
24 | ||
25 | --- a/arch/powerpc/kernel/ptrace32.c | |
26 | +++ b/arch/powerpc/kernel/ptrace32.c | |
27 | @@ -70,7 +70,8 @@ static long compat_ptrace_old(struct tas | |
28 | /* Macros to workout the correct index for the FPR in the thread struct */ | |
29 | #define FPRNUMBER(i) (((i) - PT_FPR0) >> 1) | |
30 | #define FPRHALF(i) (((i) - PT_FPR0) & 1) | |
31 | -#define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) + FPRHALF(i) | |
32 | +#define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) * 2 + FPRHALF(i) | |
33 | +#define FPRINDEX_3264(i) (TS_FPRWIDTH * ((i) - PT_FPR0)) | |
34 | ||
35 | static int compat_ptrace_getsiginfo(struct task_struct *child, compat_siginfo_t __user *data) | |
36 | { | |
37 | @@ -192,8 +193,9 @@ long compat_arch_ptrace(struct task_stru | |
38 | CHECK_FULL_REGS(child->thread.regs); | |
39 | if (numReg >= PT_FPR0) { | |
40 | flush_fp_to_thread(child); | |
41 | - tmp = ((unsigned long int *)child->thread.fpr) | |
42 | - [FPRINDEX(numReg)]; | |
43 | + /* get 64 bit FPR */ | |
44 | + tmp = ((u64 *)child->thread.fpr) | |
45 | + [FPRINDEX_3264(numReg)]; | |
46 | } else { /* register within PT_REGS struct */ | |
47 | tmp = ptrace_get_reg(child, numReg); | |
48 | } | |
49 | @@ -286,8 +288,13 @@ long compat_arch_ptrace(struct task_stru | |
50 | freg = (freg & 0xfffffffful) | (data << 32); | |
51 | ret = ptrace_put_reg(child, numReg, freg); | |
52 | } else { | |
53 | + u64 *tmp; | |
54 | flush_fp_to_thread(child); | |
55 | - ((unsigned int *)child->thread.regs)[index] = data; | |
56 | + /* get 64 bit FPR ... */ | |
57 | + tmp = &(((u64 *)child->thread.fpr) | |
58 | + [FPRINDEX_3264(numReg)]); | |
59 | + /* ... write the 32 bit part we want */ | |
60 | + ((u32 *)tmp)[index % 2] = data; | |
61 | ret = 0; | |
62 | } | |
63 | break; |