diff options
author | Michael Neuling <mikey@neuling.org> | 2008-07-02 00:06:37 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-07-03 02:58:11 -0400 |
commit | 6a274c08f2f4dfac7167bbd849621f3a2b55d424 (patch) | |
tree | 1bad45a11c1e436ffbcb84107783da0e423925f9 /arch/powerpc/kernel/signal_64.c | |
parent | 2d1b2027626d5151fff8ef7c06ca8e7876a1a510 (diff) |
powerpc: Clean up copy_to/from_user for vsx and fpr
This merges and cleans up some of the ugly copy/to from user code
which is required for the new fpr and vsx layout in the thread_struct.
Also fixes some hard coded buffer sizes and removes a redundant
fpr_flush_to_thread.
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/signal_64.c')
-rw-r--r-- | arch/powerpc/kernel/signal_64.c | 43 |
1 files changed, 11 insertions, 32 deletions
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 8214e57aab67..93ebfb6944b6 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -89,10 +89,6 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
89 | #endif | 89 | #endif |
90 | unsigned long msr = regs->msr; | 90 | unsigned long msr = regs->msr; |
91 | long err = 0; | 91 | long err = 0; |
92 | #ifdef CONFIG_VSX | ||
93 | double buf[FP_REGS_SIZE]; | ||
94 | int i; | ||
95 | #endif | ||
96 | 92 | ||
97 | flush_fp_to_thread(current); | 93 | flush_fp_to_thread(current); |
98 | 94 | ||
@@ -117,12 +113,9 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
117 | err |= __put_user(0, &sc->v_regs); | 113 | err |= __put_user(0, &sc->v_regs); |
118 | #endif /* CONFIG_ALTIVEC */ | 114 | #endif /* CONFIG_ALTIVEC */ |
119 | flush_fp_to_thread(current); | 115 | flush_fp_to_thread(current); |
116 | /* copy fpr regs and fpscr */ | ||
117 | err |= copy_fpr_to_user(&sc->fp_regs, current); | ||
120 | #ifdef CONFIG_VSX | 118 | #ifdef CONFIG_VSX |
121 | /* Copy FP to local buffer then write that out */ | ||
122 | for (i = 0; i < 32 ; i++) | ||
123 | buf[i] = current->thread.TS_FPR(i); | ||
124 | memcpy(&buf[i], ¤t->thread.fpscr, sizeof(double)); | ||
125 | err |= __copy_to_user(&sc->fp_regs, buf, FP_REGS_SIZE); | ||
126 | /* | 119 | /* |
127 | * Copy VSX low doubleword to local buffer for formatting, | 120 | * Copy VSX low doubleword to local buffer for formatting, |
128 | * then out to userspace. Update v_regs to point after the | 121 | * then out to userspace. Update v_regs to point after the |
@@ -131,17 +124,12 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
131 | if (current->thread.used_vsr) { | 124 | if (current->thread.used_vsr) { |
132 | flush_vsx_to_thread(current); | 125 | flush_vsx_to_thread(current); |
133 | v_regs += ELF_NVRREG; | 126 | v_regs += ELF_NVRREG; |
134 | for (i = 0; i < 32 ; i++) | 127 | err |= copy_vsx_to_user(v_regs, current); |
135 | buf[i] = current->thread.fpr[i][TS_VSRLOWOFFSET]; | ||
136 | err |= __copy_to_user(v_regs, buf, 32 * sizeof(double)); | ||
137 | /* set MSR_VSX in the MSR value in the frame to | 128 | /* set MSR_VSX in the MSR value in the frame to |
138 | * indicate that sc->vs_reg) contains valid data. | 129 | * indicate that sc->vs_reg) contains valid data. |
139 | */ | 130 | */ |
140 | msr |= MSR_VSX; | 131 | msr |= MSR_VSX; |
141 | } | 132 | } |
142 | #else /* CONFIG_VSX */ | ||
143 | /* copy fpr regs and fpscr */ | ||
144 | err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); | ||
145 | #endif /* CONFIG_VSX */ | 133 | #endif /* CONFIG_VSX */ |
146 | err |= __put_user(&sc->gp_regs, &sc->regs); | 134 | err |= __put_user(&sc->gp_regs, &sc->regs); |
147 | WARN_ON(!FULL_REGS(regs)); | 135 | WARN_ON(!FULL_REGS(regs)); |
@@ -165,13 +153,12 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
165 | #ifdef CONFIG_ALTIVEC | 153 | #ifdef CONFIG_ALTIVEC |
166 | elf_vrreg_t __user *v_regs; | 154 | elf_vrreg_t __user *v_regs; |
167 | #endif | 155 | #endif |
168 | #ifdef CONFIG_VSX | ||
169 | double buf[FP_REGS_SIZE]; | ||
170 | int i; | ||
171 | #endif | ||
172 | unsigned long err = 0; | 156 | unsigned long err = 0; |
173 | unsigned long save_r13 = 0; | 157 | unsigned long save_r13 = 0; |
174 | unsigned long msr; | 158 | unsigned long msr; |
159 | #ifdef CONFIG_VSX | ||
160 | int i; | ||
161 | #endif | ||
175 | 162 | ||
176 | /* If this is not a signal return, we preserve the TLS in r13 */ | 163 | /* If this is not a signal return, we preserve the TLS in r13 */ |
177 | if (!sig) | 164 | if (!sig) |
@@ -234,15 +221,9 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
234 | else | 221 | else |
235 | current->thread.vrsave = 0; | 222 | current->thread.vrsave = 0; |
236 | #endif /* CONFIG_ALTIVEC */ | 223 | #endif /* CONFIG_ALTIVEC */ |
237 | #ifdef CONFIG_VSX | ||
238 | /* restore floating point */ | 224 | /* restore floating point */ |
239 | err |= __copy_from_user(buf, &sc->fp_regs, FP_REGS_SIZE); | 225 | err |= copy_fpr_from_user(current, &sc->fp_regs); |
240 | if (err) | 226 | #ifdef CONFIG_VSX |
241 | return err; | ||
242 | for (i = 0; i < 32 ; i++) | ||
243 | current->thread.TS_FPR(i) = buf[i]; | ||
244 | memcpy(¤t->thread.fpscr, &buf[i], sizeof(double)); | ||
245 | |||
246 | /* | 227 | /* |
247 | * Get additional VSX data. Update v_regs to point after the | 228 | * Get additional VSX data. Update v_regs to point after the |
248 | * VMX data. Copy VSX low doubleword from userspace to local | 229 | * VMX data. Copy VSX low doubleword from userspace to local |
@@ -250,14 +231,12 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
250 | */ | 231 | */ |
251 | v_regs += ELF_NVRREG; | 232 | v_regs += ELF_NVRREG; |
252 | if ((msr & MSR_VSX) != 0) | 233 | if ((msr & MSR_VSX) != 0) |
253 | err |= __copy_from_user(buf, v_regs, 32 * sizeof(double)); | 234 | err |= copy_vsx_from_user(current, v_regs); |
254 | else | 235 | else |
255 | memset(buf, 0, 32 * sizeof(double)); | 236 | for (i = 0; i < 32 ; i++) |
237 | current->thread.fpr[i][TS_VSRLOWOFFSET] = 0; | ||
256 | 238 | ||
257 | for (i = 0; i < 32 ; i++) | ||
258 | current->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i]; | ||
259 | #else | 239 | #else |
260 | err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); | ||
261 | #endif | 240 | #endif |
262 | return err; | 241 | return err; |
263 | } | 242 | } |