diff options
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r-- | arch/mips/kernel/signal32.c | 211 |
1 files changed, 97 insertions, 114 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 1a99a57739e1..5d102efbdbea 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -160,6 +160,103 @@ struct rt_sigframe32 { | |||
160 | 160 | ||
161 | #endif /* !ICACHE_REFILLS_WORKAROUND_WAR */ | 161 | #endif /* !ICACHE_REFILLS_WORKAROUND_WAR */ |
162 | 162 | ||
163 | /* | ||
164 | * sigcontext handlers | ||
165 | */ | ||
166 | static int setup_sigcontext32(struct pt_regs *regs, | ||
167 | struct sigcontext32 __user *sc) | ||
168 | { | ||
169 | int err = 0; | ||
170 | int i; | ||
171 | |||
172 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); | ||
173 | err |= __put_user(regs->cp0_status, &sc->sc_status); | ||
174 | |||
175 | err |= __put_user(0, &sc->sc_regs[0]); | ||
176 | for (i = 1; i < 32; i++) | ||
177 | err |= __put_user(regs->regs[i], &sc->sc_regs[i]); | ||
178 | |||
179 | err |= __put_user(regs->hi, &sc->sc_mdhi); | ||
180 | err |= __put_user(regs->lo, &sc->sc_mdlo); | ||
181 | if (cpu_has_dsp) { | ||
182 | err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); | ||
183 | err |= __put_user(mfhi1(), &sc->sc_hi1); | ||
184 | err |= __put_user(mflo1(), &sc->sc_lo1); | ||
185 | err |= __put_user(mfhi2(), &sc->sc_hi2); | ||
186 | err |= __put_user(mflo2(), &sc->sc_lo2); | ||
187 | err |= __put_user(mfhi3(), &sc->sc_hi3); | ||
188 | err |= __put_user(mflo3(), &sc->sc_lo3); | ||
189 | } | ||
190 | |||
191 | err |= __put_user(!!used_math(), &sc->sc_used_math); | ||
192 | |||
193 | if (used_math()) { | ||
194 | /* | ||
195 | * Save FPU state to signal context. Signal handler | ||
196 | * will "inherit" current FPU state. | ||
197 | */ | ||
198 | preempt_disable(); | ||
199 | |||
200 | if (!is_fpu_owner()) { | ||
201 | own_fpu(); | ||
202 | restore_fp(current); | ||
203 | } | ||
204 | err |= save_fp_context32(sc); | ||
205 | |||
206 | preempt_enable(); | ||
207 | } | ||
208 | return err; | ||
209 | } | ||
210 | |||
211 | static int restore_sigcontext32(struct pt_regs *regs, | ||
212 | struct sigcontext32 __user *sc) | ||
213 | { | ||
214 | u32 used_math; | ||
215 | int err = 0; | ||
216 | s32 treg; | ||
217 | int i; | ||
218 | |||
219 | /* Always make any pending restarted system calls return -EINTR */ | ||
220 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
221 | |||
222 | err |= __get_user(regs->cp0_epc, &sc->sc_pc); | ||
223 | err |= __get_user(regs->hi, &sc->sc_mdhi); | ||
224 | err |= __get_user(regs->lo, &sc->sc_mdlo); | ||
225 | if (cpu_has_dsp) { | ||
226 | err |= __get_user(treg, &sc->sc_hi1); mthi1(treg); | ||
227 | err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg); | ||
228 | err |= __get_user(treg, &sc->sc_hi2); mthi2(treg); | ||
229 | err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg); | ||
230 | err |= __get_user(treg, &sc->sc_hi3); mthi3(treg); | ||
231 | err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg); | ||
232 | err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK); | ||
233 | } | ||
234 | |||
235 | for (i = 1; i < 32; i++) | ||
236 | err |= __get_user(regs->regs[i], &sc->sc_regs[i]); | ||
237 | |||
238 | err |= __get_user(used_math, &sc->sc_used_math); | ||
239 | conditional_used_math(used_math); | ||
240 | |||
241 | preempt_disable(); | ||
242 | |||
243 | if (used_math()) { | ||
244 | /* restore fpu context if we have used it before */ | ||
245 | own_fpu(); | ||
246 | err |= restore_fp_context32(sc); | ||
247 | } else { | ||
248 | /* signal handler may have used FPU. Give it up. */ | ||
249 | lose_fpu(); | ||
250 | } | ||
251 | |||
252 | preempt_enable(); | ||
253 | |||
254 | return err; | ||
255 | } | ||
256 | |||
257 | /* | ||
258 | * | ||
259 | */ | ||
163 | extern void __put_sigset_unknown_nsig(void); | 260 | extern void __put_sigset_unknown_nsig(void); |
164 | extern void __get_sigset_unknown_nsig(void); | 261 | extern void __get_sigset_unknown_nsig(void); |
165 | 262 | ||
@@ -347,63 +444,6 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) | |||
347 | return ret; | 444 | return ret; |
348 | } | 445 | } |
349 | 446 | ||
350 | static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 __user *sc) | ||
351 | { | ||
352 | u32 used_math; | ||
353 | int err = 0; | ||
354 | s32 treg; | ||
355 | |||
356 | /* Always make any pending restarted system calls return -EINTR */ | ||
357 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
358 | |||
359 | err |= __get_user(regs->cp0_epc, &sc->sc_pc); | ||
360 | err |= __get_user(regs->hi, &sc->sc_mdhi); | ||
361 | err |= __get_user(regs->lo, &sc->sc_mdlo); | ||
362 | if (cpu_has_dsp) { | ||
363 | err |= __get_user(treg, &sc->sc_hi1); mthi1(treg); | ||
364 | err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg); | ||
365 | err |= __get_user(treg, &sc->sc_hi2); mthi2(treg); | ||
366 | err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg); | ||
367 | err |= __get_user(treg, &sc->sc_hi3); mthi3(treg); | ||
368 | err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg); | ||
369 | err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK); | ||
370 | } | ||
371 | |||
372 | #define restore_gp_reg(i) do { \ | ||
373 | err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \ | ||
374 | } while(0) | ||
375 | restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3); | ||
376 | restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6); | ||
377 | restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9); | ||
378 | restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12); | ||
379 | restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15); | ||
380 | restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18); | ||
381 | restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21); | ||
382 | restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24); | ||
383 | restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27); | ||
384 | restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30); | ||
385 | restore_gp_reg(31); | ||
386 | #undef restore_gp_reg | ||
387 | |||
388 | err |= __get_user(used_math, &sc->sc_used_math); | ||
389 | conditional_used_math(used_math); | ||
390 | |||
391 | preempt_disable(); | ||
392 | |||
393 | if (used_math()) { | ||
394 | /* restore fpu context if we have used it before */ | ||
395 | own_fpu(); | ||
396 | err |= restore_fp_context32(sc); | ||
397 | } else { | ||
398 | /* signal handler may have used FPU. Give it up. */ | ||
399 | lose_fpu(); | ||
400 | } | ||
401 | |||
402 | preempt_enable(); | ||
403 | |||
404 | return err; | ||
405 | } | ||
406 | |||
407 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) | 447 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) |
408 | { | 448 | { |
409 | int err; | 449 | int err; |
@@ -547,63 +587,6 @@ badframe: | |||
547 | force_sig(SIGSEGV, current); | 587 | force_sig(SIGSEGV, current); |
548 | } | 588 | } |
549 | 589 | ||
550 | static inline int setup_sigcontext32(struct pt_regs *regs, | ||
551 | struct sigcontext32 __user *sc) | ||
552 | { | ||
553 | int err = 0; | ||
554 | |||
555 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); | ||
556 | err |= __put_user(regs->cp0_status, &sc->sc_status); | ||
557 | |||
558 | #define save_gp_reg(i) { \ | ||
559 | err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \ | ||
560 | } while(0) | ||
561 | __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); | ||
562 | save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); | ||
563 | save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10); | ||
564 | save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14); | ||
565 | save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18); | ||
566 | save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22); | ||
567 | save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26); | ||
568 | save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30); | ||
569 | save_gp_reg(31); | ||
570 | #undef save_gp_reg | ||
571 | |||
572 | err |= __put_user(regs->hi, &sc->sc_mdhi); | ||
573 | err |= __put_user(regs->lo, &sc->sc_mdlo); | ||
574 | if (cpu_has_dsp) { | ||
575 | err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); | ||
576 | err |= __put_user(mfhi1(), &sc->sc_hi1); | ||
577 | err |= __put_user(mflo1(), &sc->sc_lo1); | ||
578 | err |= __put_user(mfhi2(), &sc->sc_hi2); | ||
579 | err |= __put_user(mflo2(), &sc->sc_lo2); | ||
580 | err |= __put_user(mfhi3(), &sc->sc_hi3); | ||
581 | err |= __put_user(mflo3(), &sc->sc_lo3); | ||
582 | } | ||
583 | |||
584 | err |= __put_user(!!used_math(), &sc->sc_used_math); | ||
585 | |||
586 | if (!used_math()) | ||
587 | goto out; | ||
588 | |||
589 | /* | ||
590 | * Save FPU state to signal context. Signal handler will "inherit" | ||
591 | * current FPU state. | ||
592 | */ | ||
593 | preempt_disable(); | ||
594 | |||
595 | if (!is_fpu_owner()) { | ||
596 | own_fpu(); | ||
597 | restore_fp(current); | ||
598 | } | ||
599 | err |= save_fp_context32(sc); | ||
600 | |||
601 | preempt_enable(); | ||
602 | |||
603 | out: | ||
604 | return err; | ||
605 | } | ||
606 | |||
607 | int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 590 | int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, |
608 | int signr, sigset_t *set) | 591 | int signr, sigset_t *set) |
609 | { | 592 | { |