diff options
Diffstat (limited to 'arch/x86/ia32')
-rw-r--r-- | arch/x86/ia32/ia32_signal.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 20af4c79579a..a05bf0fb7415 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
@@ -179,9 +179,10 @@ struct sigframe | |||
179 | u32 pretcode; | 179 | u32 pretcode; |
180 | int sig; | 180 | int sig; |
181 | struct sigcontext_ia32 sc; | 181 | struct sigcontext_ia32 sc; |
182 | struct _fpstate_ia32 fpstate; | 182 | struct _fpstate_ia32 fpstate_unused; /* look at kernel/sigframe.h */ |
183 | unsigned int extramask[_COMPAT_NSIG_WORDS-1]; | 183 | unsigned int extramask[_COMPAT_NSIG_WORDS-1]; |
184 | char retcode[8]; | 184 | char retcode[8]; |
185 | /* fp state follows here */ | ||
185 | }; | 186 | }; |
186 | 187 | ||
187 | struct rt_sigframe | 188 | struct rt_sigframe |
@@ -192,8 +193,8 @@ struct rt_sigframe | |||
192 | u32 puc; | 193 | u32 puc; |
193 | compat_siginfo_t info; | 194 | compat_siginfo_t info; |
194 | struct ucontext_ia32 uc; | 195 | struct ucontext_ia32 uc; |
195 | struct _fpstate_ia32 fpstate; | ||
196 | char retcode[8]; | 196 | char retcode[8]; |
197 | /* fp state follows here */ | ||
197 | }; | 198 | }; |
198 | 199 | ||
199 | #define COPY(x) { \ | 200 | #define COPY(x) { \ |
@@ -402,7 +403,8 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, | |||
402 | * Determine which stack to use.. | 403 | * Determine which stack to use.. |
403 | */ | 404 | */ |
404 | static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 405 | static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, |
405 | size_t frame_size) | 406 | size_t frame_size, |
407 | struct _fpstate_ia32 **fpstate) | ||
406 | { | 408 | { |
407 | unsigned long sp; | 409 | unsigned long sp; |
408 | 410 | ||
@@ -421,6 +423,11 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
421 | ka->sa.sa_restorer) | 423 | ka->sa.sa_restorer) |
422 | sp = (unsigned long) ka->sa.sa_restorer; | 424 | sp = (unsigned long) ka->sa.sa_restorer; |
423 | 425 | ||
426 | if (used_math()) { | ||
427 | sp = sp - sig_xstate_ia32_size; | ||
428 | *fpstate = (struct _fpstate_ia32 *) sp; | ||
429 | } | ||
430 | |||
424 | sp -= frame_size; | 431 | sp -= frame_size; |
425 | /* Align the stack pointer according to the i386 ABI, | 432 | /* Align the stack pointer according to the i386 ABI, |
426 | * i.e. so that on function entry ((sp + 4) & 15) == 0. */ | 433 | * i.e. so that on function entry ((sp + 4) & 15) == 0. */ |
@@ -434,6 +441,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
434 | struct sigframe __user *frame; | 441 | struct sigframe __user *frame; |
435 | void __user *restorer; | 442 | void __user *restorer; |
436 | int err = 0; | 443 | int err = 0; |
444 | struct _fpstate_ia32 __user *fpstate = NULL; | ||
437 | 445 | ||
438 | /* copy_to_user optimizes that into a single 8 byte store */ | 446 | /* copy_to_user optimizes that into a single 8 byte store */ |
439 | static const struct { | 447 | static const struct { |
@@ -448,7 +456,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
448 | 0, | 456 | 0, |
449 | }; | 457 | }; |
450 | 458 | ||
451 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 459 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
452 | 460 | ||
453 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 461 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
454 | goto give_sigsegv; | 462 | goto give_sigsegv; |
@@ -457,8 +465,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
457 | if (err) | 465 | if (err) |
458 | goto give_sigsegv; | 466 | goto give_sigsegv; |
459 | 467 | ||
460 | err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs, | 468 | err |= ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); |
461 | set->sig[0]); | ||
462 | if (err) | 469 | if (err) |
463 | goto give_sigsegv; | 470 | goto give_sigsegv; |
464 | 471 | ||
@@ -522,6 +529,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
522 | struct rt_sigframe __user *frame; | 529 | struct rt_sigframe __user *frame; |
523 | void __user *restorer; | 530 | void __user *restorer; |
524 | int err = 0; | 531 | int err = 0; |
532 | struct _fpstate_ia32 __user *fpstate = NULL; | ||
525 | 533 | ||
526 | /* __copy_to_user optimizes that into a single 8 byte store */ | 534 | /* __copy_to_user optimizes that into a single 8 byte store */ |
527 | static const struct { | 535 | static const struct { |
@@ -537,7 +545,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
537 | 0, | 545 | 0, |
538 | }; | 546 | }; |
539 | 547 | ||
540 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 548 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
541 | 549 | ||
542 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 550 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
543 | goto give_sigsegv; | 551 | goto give_sigsegv; |
@@ -556,7 +564,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
556 | err |= __put_user(sas_ss_flags(regs->sp), | 564 | err |= __put_user(sas_ss_flags(regs->sp), |
557 | &frame->uc.uc_stack.ss_flags); | 565 | &frame->uc.uc_stack.ss_flags); |
558 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 566 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
559 | err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, | 567 | err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, |
560 | regs, set->sig[0]); | 568 | regs, set->sig[0]); |
561 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 569 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
562 | if (err) | 570 | if (err) |