aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_64.c
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2008-06-25 00:07:18 -0400
committerPaul Mackerras <paulus@samba.org>2008-06-30 21:28:50 -0400
commitce48b2100785e5ca629fb3aa8e3b50aca808f692 (patch)
tree63532ff7cc68b18ca4902bd10e03fcbaaf01cade /arch/powerpc/kernel/signal_64.c
parent72ffff5b1792b0fa4d40a8e2f3276fff999820ec (diff)
powerpc: Add VSX context save/restore, ptrace and signal support
This patch extends the floating point save and restore code to use the VSX load/stores when VSX is available. This will make FP context save/restore marginally slower on FP only code, when VSX is available, as it has to load/store 128bits rather than just 64bits. Mixing FP, VMX and VSX code will get constant architected state. The signals interface is extended to enable access to VSR 0-31 doubleword 1 after discussions with tool chain maintainers. Backward compatibility is maintained. The ptrace interface is also extended to allow access to VSR 0-31 full registers. 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.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index a587b33cd6b9..34f37e59bacc 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -123,6 +123,22 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
123 buf[i] = current->thread.TS_FPR(i); 123 buf[i] = current->thread.TS_FPR(i);
124 memcpy(&buf[i], &current->thread.fpscr, sizeof(double)); 124 memcpy(&buf[i], &current->thread.fpscr, sizeof(double));
125 err |= __copy_to_user(&sc->fp_regs, buf, FP_REGS_SIZE); 125 err |= __copy_to_user(&sc->fp_regs, buf, FP_REGS_SIZE);
126 /*
127 * Copy VSX low doubleword to local buffer for formatting,
128 * then out to userspace. Update v_regs to point after the
129 * VMX data.
130 */
131 if (current->thread.used_vsr) {
132 flush_vsx_to_thread(current);
133 v_regs += ELF_NVRREG;
134 for (i = 0; i < 32 ; i++)
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
138 * indicate that sc->vs_reg) contains valid data.
139 */
140 msr |= MSR_VSX;
141 }
126#else /* CONFIG_VSX */ 142#else /* CONFIG_VSX */
127 /* copy fpr regs and fpscr */ 143 /* copy fpr regs and fpscr */
128 err |= __copy_to_user(&sc->fp_regs, &current->thread.fpr, FP_REGS_SIZE); 144 err |= __copy_to_user(&sc->fp_regs, &current->thread.fpr, FP_REGS_SIZE);
@@ -197,7 +213,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
197 * This has to be done before copying stuff into current->thread.fpr/vr 213 * This has to be done before copying stuff into current->thread.fpr/vr
198 * for the reasons explained in the previous comment. 214 * for the reasons explained in the previous comment.
199 */ 215 */
200 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC); 216 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC | MSR_VSX);
201 217
202#ifdef CONFIG_ALTIVEC 218#ifdef CONFIG_ALTIVEC
203 err |= __get_user(v_regs, &sc->v_regs); 219 err |= __get_user(v_regs, &sc->v_regs);
@@ -226,6 +242,19 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
226 current->thread.TS_FPR(i) = buf[i]; 242 current->thread.TS_FPR(i) = buf[i];
227 memcpy(&current->thread.fpscr, &buf[i], sizeof(double)); 243 memcpy(&current->thread.fpscr, &buf[i], sizeof(double));
228 244
245 /*
246 * Get additional VSX data. Update v_regs to point after the
247 * VMX data. Copy VSX low doubleword from userspace to local
248 * buffer for formatting, then into the taskstruct.
249 */
250 v_regs += ELF_NVRREG;
251 if ((msr & MSR_VSX) != 0)
252 err |= __copy_from_user(buf, v_regs, 32 * sizeof(double));
253 else
254 memset(buf, 0, 32 * sizeof(double));
255
256 for (i = 0; i < 32 ; i++)
257 current->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i];
229#else 258#else
230 err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); 259 err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
231#endif 260#endif