aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/ia32
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/ia32')
-rw-r--r--arch/x86/ia32/ia32_signal.c24
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
187struct rt_sigframe 188struct 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 */
404static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, 405static 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)