aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_32.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_32.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_32.c')
-rw-r--r--arch/powerpc/kernel/signal_32.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index f7fa395b9fb5..349d3487d920 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -378,6 +378,21 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
378 memcpy(&buf[i], &current->thread.fpscr, sizeof(double)); 378 memcpy(&buf[i], &current->thread.fpscr, sizeof(double));
379 if (__copy_to_user(&frame->mc_fregs, buf, ELF_NFPREG * sizeof(double))) 379 if (__copy_to_user(&frame->mc_fregs, buf, ELF_NFPREG * sizeof(double)))
380 return 1; 380 return 1;
381 /*
382 * Copy VSR 0-31 upper half from thread_struct to local
383 * buffer, then write that to userspace. Also set MSR_VSX in
384 * the saved MSR value to indicate that frame->mc_vregs
385 * contains valid data
386 */
387 if (current->thread.used_vsr) {
388 flush_vsx_to_thread(current);
389 for (i = 0; i < 32 ; i++)
390 buf[i] = current->thread.fpr[i][TS_VSRLOWOFFSET];
391 if (__copy_to_user(&frame->mc_vsregs, buf,
392 ELF_NVSRHALFREG * sizeof(double)))
393 return 1;
394 msr |= MSR_VSX;
395 }
381#else 396#else
382 /* save floating-point registers */ 397 /* save floating-point registers */
383 if (__copy_to_user(&frame->mc_fregs, current->thread.fpr, 398 if (__copy_to_user(&frame->mc_fregs, current->thread.fpr,
@@ -482,6 +497,24 @@ static long restore_user_regs(struct pt_regs *regs,
482 for (i = 0; i < 32 ; i++) 497 for (i = 0; i < 32 ; i++)
483 current->thread.TS_FPR(i) = buf[i]; 498 current->thread.TS_FPR(i) = buf[i];
484 memcpy(&current->thread.fpscr, &buf[i], sizeof(double)); 499 memcpy(&current->thread.fpscr, &buf[i], sizeof(double));
500 /*
501 * Force the process to reload the VSX registers from
502 * current->thread when it next does VSX instruction.
503 */
504 regs->msr &= ~MSR_VSX;
505 if (msr & MSR_VSX) {
506 /*
507 * Restore altivec registers from the stack to a local
508 * buffer, then write this out to the thread_struct
509 */
510 if (__copy_from_user(buf, &sr->mc_vsregs,
511 sizeof(sr->mc_vsregs)))
512 return 1;
513 for (i = 0; i < 32 ; i++)
514 current->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i];
515 } else if (current->thread.used_vsr)
516 for (i = 0; i < 32 ; i++)
517 current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
485#else 518#else
486 if (__copy_from_user(current->thread.fpr, &sr->mc_fregs, 519 if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
487 sizeof(sr->mc_fregs))) 520 sizeof(sr->mc_fregs)))