diff options
Diffstat (limited to 'arch/powerpc/kernel/signal_32.c')
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index b057e6852a7..f7fa395b9fb 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, 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 */ |