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:46 -0400
commitc6e6771b87d4e339d27f1383c8a808ae9b4ee5b8 (patch)
tree1900b7350ec685c3a31f2233fd88a57e34725b5c /arch/powerpc/kernel/signal_32.c
parent6f3d8e6947ec98e358514fc0f7b2e37fe88a21bb (diff)
powerpc: Introduce VSX thread_struct and CONFIG_VSX
The layout of the new VSR registers and how they overlap on top of the legacy FPR and VR registers is: VSR doubleword 0 VSR doubleword 1 ---------------------------------------------------------------- VSR[0] | FPR[0] | | ---------------------------------------------------------------- VSR[1] | FPR[1] | | ---------------------------------------------------------------- | ... | | | ... | | ---------------------------------------------------------------- VSR[30] | FPR[30] | | ---------------------------------------------------------------- VSR[31] | FPR[31] | | ---------------------------------------------------------------- VSR[32] | VR[0] | ---------------------------------------------------------------- VSR[33] | VR[1] | ---------------------------------------------------------------- | ... | | ... | ---------------------------------------------------------------- VSR[62] | VR[30] | ---------------------------------------------------------------- VSR[63] | VR[31] | ---------------------------------------------------------------- VSX has 64 128bit registers. The first 32 regs overlap with the FP registers and hence extend them with and additional 64 bits. The second 32 regs overlap with the VMX registers. This commit introduces the thread_struct changes required to reflect this register layout. Ptrace and signals code is updated so that the floating point registers are correctly accessed from the thread_struct when CONFIG_VSX is enabled. 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.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 */