diff options
author | Michael Neuling <mikey@neuling.org> | 2008-06-25 00:07:18 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-06-30 21:28:50 -0400 |
commit | ce48b2100785e5ca629fb3aa8e3b50aca808f692 (patch) | |
tree | 63532ff7cc68b18ca4902bd10e03fcbaaf01cade /arch/powerpc/kernel/signal_64.c | |
parent | 72ffff5b1792b0fa4d40a8e2f3276fff999820ec (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.c | 31 |
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], ¤t->thread.fpscr, sizeof(double)); | 124 | memcpy(&buf[i], ¤t->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, ¤t->thread.fpr, FP_REGS_SIZE); | 144 | err |= __copy_to_user(&sc->fp_regs, ¤t->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(¤t->thread.fpscr, &buf[i], sizeof(double)); | 243 | memcpy(¤t->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(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); | 259 | err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); |
231 | #endif | 260 | #endif |