aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/signal_64.c')
-rw-r--r--arch/powerpc/kernel/signal_64.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index da7c058e373..a587b33cd6b 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -89,6 +89,10 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
89#endif 89#endif
90 unsigned long msr = regs->msr; 90 unsigned long msr = regs->msr;
91 long err = 0; 91 long err = 0;
92#ifdef CONFIG_VSX
93 double buf[FP_REGS_SIZE];
94 int i;
95#endif
92 96
93 flush_fp_to_thread(current); 97 flush_fp_to_thread(current);
94 98
@@ -112,11 +116,21 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
112#else /* CONFIG_ALTIVEC */ 116#else /* CONFIG_ALTIVEC */
113 err |= __put_user(0, &sc->v_regs); 117 err |= __put_user(0, &sc->v_regs);
114#endif /* CONFIG_ALTIVEC */ 118#endif /* CONFIG_ALTIVEC */
119 flush_fp_to_thread(current);
120#ifdef CONFIG_VSX
121 /* Copy FP to local buffer then write that out */
122 for (i = 0; i < 32 ; i++)
123 buf[i] = current->thread.TS_FPR(i);
124 memcpy(&buf[i], &current->thread.fpscr, sizeof(double));
125 err |= __copy_to_user(&sc->fp_regs, buf, FP_REGS_SIZE);
126#else /* CONFIG_VSX */
127 /* copy fpr regs and fpscr */
128 err |= __copy_to_user(&sc->fp_regs, &current->thread.fpr, FP_REGS_SIZE);
129#endif /* CONFIG_VSX */
115 err |= __put_user(&sc->gp_regs, &sc->regs); 130 err |= __put_user(&sc->gp_regs, &sc->regs);
116 WARN_ON(!FULL_REGS(regs)); 131 WARN_ON(!FULL_REGS(regs));
117 err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); 132 err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE);
118 err |= __put_user(msr, &sc->gp_regs[PT_MSR]); 133 err |= __put_user(msr, &sc->gp_regs[PT_MSR]);
119 err |= __copy_to_user(&sc->fp_regs, &current->thread.fpr, FP_REGS_SIZE);
120 err |= __put_user(signr, &sc->signal); 134 err |= __put_user(signr, &sc->signal);
121 err |= __put_user(handler, &sc->handler); 135 err |= __put_user(handler, &sc->handler);
122 if (set != NULL) 136 if (set != NULL)
@@ -135,6 +149,9 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
135#ifdef CONFIG_ALTIVEC 149#ifdef CONFIG_ALTIVEC
136 elf_vrreg_t __user *v_regs; 150 elf_vrreg_t __user *v_regs;
137#endif 151#endif
152#ifdef CONFIG_VSX
153 double buf[FP_REGS_SIZE];
154#endif
138 unsigned long err = 0; 155 unsigned long err = 0;
139 unsigned long save_r13 = 0; 156 unsigned long save_r13 = 0;
140 elf_greg_t *gregs = (elf_greg_t *)regs; 157 elf_greg_t *gregs = (elf_greg_t *)regs;
@@ -182,8 +199,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
182 */ 199 */
183 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC); 200 regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
184 201
185 err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
186
187#ifdef CONFIG_ALTIVEC 202#ifdef CONFIG_ALTIVEC
188 err |= __get_user(v_regs, &sc->v_regs); 203 err |= __get_user(v_regs, &sc->v_regs);
189 if (err) 204 if (err)
@@ -202,7 +217,18 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
202 else 217 else
203 current->thread.vrsave = 0; 218 current->thread.vrsave = 0;
204#endif /* CONFIG_ALTIVEC */ 219#endif /* CONFIG_ALTIVEC */
220#ifdef CONFIG_VSX
221 /* restore floating point */
222 err |= __copy_from_user(buf, &sc->fp_regs, FP_REGS_SIZE);
223 if (err)
224 return err;
225 for (i = 0; i < 32 ; i++)
226 current->thread.TS_FPR(i) = buf[i];
227 memcpy(&current->thread.fpscr, &buf[i], sizeof(double));
205 228
229#else
230 err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
231#endif
206 return err; 232 return err;
207} 233}
208 234