aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/signal_32.c')
-rw-r--r--arch/powerpc/kernel/signal_32.c59
1 files changed, 45 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index b057e6852a7d..f7fa395b9fb5 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -337,14 +337,16 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
337 int sigret) 337 int sigret)
338{ 338{
339 unsigned long msr = regs->msr; 339 unsigned long msr = regs->msr;
340#ifdef CONFIG_VSX
341 double buf[32];
342 int i;
343#endif
340 344
341 /* Make sure floating point registers are stored in regs */ 345 /* Make sure floating point registers are stored in regs */
342 flush_fp_to_thread(current); 346 flush_fp_to_thread(current);
343 347
344 /* save general and floating-point registers */ 348 /* save general registers */
345 if (save_general_regs(regs, frame) || 349 if (save_general_regs(regs, frame))
346 __copy_to_user(&frame->mc_fregs, current->thread.fpr,
347 ELF_NFPREG * sizeof(double)))
348 return 1; 350 return 1;
349 351
350#ifdef CONFIG_ALTIVEC 352#ifdef CONFIG_ALTIVEC
@@ -368,7 +370,20 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
368 if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32])) 370 if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32]))
369 return 1; 371 return 1;
370#endif /* CONFIG_ALTIVEC */ 372#endif /* CONFIG_ALTIVEC */
371 373#ifdef CONFIG_VSX
374 /* save FPR copy to local buffer then write to the thread_struct */
375 flush_fp_to_thread(current);
376 for (i = 0; i < 32 ; i++)
377 buf[i] = current->thread.TS_FPR(i);
378 memcpy(&buf[i], &current->thread.fpscr, sizeof(double));
379 if (__copy_to_user(&frame->mc_fregs, buf, ELF_NFPREG * sizeof(double)))
380 return 1;
381#else
382 /* save floating-point registers */
383 if (__copy_to_user(&frame->mc_fregs, current->thread.fpr,
384 ELF_NFPREG * sizeof(double)))
385 return 1;
386#endif /* CONFIG_VSX */
372#ifdef CONFIG_SPE 387#ifdef CONFIG_SPE
373 /* save spe registers */ 388 /* save spe registers */
374 if (current->thread.used_spe) { 389 if (current->thread.used_spe) {
@@ -411,6 +426,10 @@ static long restore_user_regs(struct pt_regs *regs,
411 long err; 426 long err;
412 unsigned int save_r2 = 0; 427 unsigned int save_r2 = 0;
413 unsigned long msr; 428 unsigned long msr;
429#ifdef CONFIG_VSX
430 double buf[32];
431 int i;
432#endif
414 433
415 /* 434 /*
416 * restore general registers but not including MSR or SOFTE. Also 435 * restore general registers but not including MSR or SOFTE. Also
@@ -438,16 +457,11 @@ static long restore_user_regs(struct pt_regs *regs,
438 */ 457 */
439 discard_lazy_cpu_state(); 458 discard_lazy_cpu_state();
440 459
441 /* force the process to reload the FP registers from
442 current->thread when it next does FP instructions */
443 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
444 if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
445 sizeof(sr->mc_fregs)))
446 return 1;
447
448#ifdef CONFIG_ALTIVEC 460#ifdef CONFIG_ALTIVEC
449 /* force the process to reload the altivec registers from 461 /*
450 current->thread when it next does altivec instructions */ 462 * Force the process to reload the altivec registers from
463 * current->thread when it next does altivec instructions
464 */
451 regs->msr &= ~MSR_VEC; 465 regs->msr &= ~MSR_VEC;
452 if (msr & MSR_VEC) { 466 if (msr & MSR_VEC) {
453 /* restore altivec registers from the stack */ 467 /* restore altivec registers from the stack */
@@ -462,6 +476,23 @@ static long restore_user_regs(struct pt_regs *regs,
462 return 1; 476 return 1;
463#endif /* CONFIG_ALTIVEC */ 477#endif /* CONFIG_ALTIVEC */
464 478
479#ifdef CONFIG_VSX
480 if (__copy_from_user(buf, &sr->mc_fregs,sizeof(sr->mc_fregs)))
481 return 1;
482 for (i = 0; i < 32 ; i++)
483 current->thread.TS_FPR(i) = buf[i];
484 memcpy(&current->thread.fpscr, &buf[i], sizeof(double));
485#else
486 if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
487 sizeof(sr->mc_fregs)))
488 return 1;
489#endif /* CONFIG_VSX */
490 /*
491 * force the process to reload the FP registers from
492 * current->thread when it next does FP instructions
493 */
494 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
495
465#ifdef CONFIG_SPE 496#ifdef CONFIG_SPE
466 /* force the process to reload the spe registers from 497 /* force the process to reload the spe registers from
467 current->thread when it next does spe instructions */ 498 current->thread when it next does spe instructions */