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_32.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_32.c')
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 33 |
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], ¤t->thread.fpscr, sizeof(double)); | 378 | memcpy(&buf[i], ¤t->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(¤t->thread.fpscr, &buf[i], sizeof(double)); | 499 | memcpy(¤t->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))) |