|
@@ -337,14 +337,16 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
|
|
|
int sigret)
|
|
|
{
|
|
|
unsigned long msr = regs->msr;
|
|
|
+#ifdef CONFIG_VSX
|
|
|
+ double buf[32];
|
|
|
+ int i;
|
|
|
+#endif
|
|
|
|
|
|
/* Make sure floating point registers are stored in regs */
|
|
|
flush_fp_to_thread(current);
|
|
|
|
|
|
- /* save general and floating-point registers */
|
|
|
- if (save_general_regs(regs, frame) ||
|
|
|
- __copy_to_user(&frame->mc_fregs, current->thread.fpr,
|
|
|
- ELF_NFPREG * sizeof(double)))
|
|
|
+ /* save general registers */
|
|
|
+ if (save_general_regs(regs, frame))
|
|
|
return 1;
|
|
|
|
|
|
#ifdef CONFIG_ALTIVEC
|
|
@@ -368,7 +370,20 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
|
|
|
if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32]))
|
|
|
return 1;
|
|
|
#endif /* CONFIG_ALTIVEC */
|
|
|
-
|
|
|
+#ifdef CONFIG_VSX
|
|
|
+ /* save FPR copy to local buffer then write to the thread_struct */
|
|
|
+ flush_fp_to_thread(current);
|
|
|
+ for (i = 0; i < 32 ; i++)
|
|
|
+ buf[i] = current->thread.TS_FPR(i);
|
|
|
+ memcpy(&buf[i], ¤t->thread.fpscr, sizeof(double));
|
|
|
+ if (__copy_to_user(&frame->mc_fregs, buf, ELF_NFPREG * sizeof(double)))
|
|
|
+ return 1;
|
|
|
+#else
|
|
|
+ /* save floating-point registers */
|
|
|
+ if (__copy_to_user(&frame->mc_fregs, current->thread.fpr,
|
|
|
+ ELF_NFPREG * sizeof(double)))
|
|
|
+ return 1;
|
|
|
+#endif /* CONFIG_VSX */
|
|
|
#ifdef CONFIG_SPE
|
|
|
/* save spe registers */
|
|
|
if (current->thread.used_spe) {
|
|
@@ -411,6 +426,10 @@ static long restore_user_regs(struct pt_regs *regs,
|
|
|
long err;
|
|
|
unsigned int save_r2 = 0;
|
|
|
unsigned long msr;
|
|
|
+#ifdef CONFIG_VSX
|
|
|
+ double buf[32];
|
|
|
+ int i;
|
|
|
+#endif
|
|
|
|
|
|
/*
|
|
|
* restore general registers but not including MSR or SOFTE. Also
|
|
@@ -438,16 +457,11 @@ static long restore_user_regs(struct pt_regs *regs,
|
|
|
*/
|
|
|
discard_lazy_cpu_state();
|
|
|
|
|
|
- /* force the process to reload the FP registers from
|
|
|
- current->thread when it next does FP instructions */
|
|
|
- regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
|
|
|
- if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
|
|
|
- sizeof(sr->mc_fregs)))
|
|
|
- return 1;
|
|
|
-
|
|
|
#ifdef CONFIG_ALTIVEC
|
|
|
- /* force the process to reload the altivec registers from
|
|
|
- current->thread when it next does altivec instructions */
|
|
|
+ /*
|
|
|
+ * Force the process to reload the altivec registers from
|
|
|
+ * current->thread when it next does altivec instructions
|
|
|
+ */
|
|
|
regs->msr &= ~MSR_VEC;
|
|
|
if (msr & MSR_VEC) {
|
|
|
/* restore altivec registers from the stack */
|
|
@@ -462,6 +476,23 @@ static long restore_user_regs(struct pt_regs *regs,
|
|
|
return 1;
|
|
|
#endif /* CONFIG_ALTIVEC */
|
|
|
|
|
|
+#ifdef CONFIG_VSX
|
|
|
+ if (__copy_from_user(buf, &sr->mc_fregs,sizeof(sr->mc_fregs)))
|
|
|
+ return 1;
|
|
|
+ for (i = 0; i < 32 ; i++)
|
|
|
+ current->thread.TS_FPR(i) = buf[i];
|
|
|
+ memcpy(¤t->thread.fpscr, &buf[i], sizeof(double));
|
|
|
+#else
|
|
|
+ if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
|
|
|
+ sizeof(sr->mc_fregs)))
|
|
|
+ return 1;
|
|
|
+#endif /* CONFIG_VSX */
|
|
|
+ /*
|
|
|
+ * force the process to reload the FP registers from
|
|
|
+ * current->thread when it next does FP instructions
|
|
|
+ */
|
|
|
+ regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
|
|
|
+
|
|
|
#ifdef CONFIG_SPE
|
|
|
/* force the process to reload the spe registers from
|
|
|
current->thread when it next does spe instructions */
|