diff options
Diffstat (limited to 'arch/powerpc/kernel/signal_64.c')
-rw-r--r-- | arch/powerpc/kernel/signal_64.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index da7c058e3731..a587b33cd6b9 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], ¤t->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, ¤t->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, ¤t->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(¤t->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(¤t->thread.fpscr, &buf[i], sizeof(double)); | ||
205 | 228 | ||
229 | #else | ||
230 | err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); | ||
231 | #endif | ||
206 | return err; | 232 | return err; |
207 | } | 233 | } |
208 | 234 | ||