diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2008-07-29 13:29:21 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-30 13:49:25 -0400 |
commit | 3c1c7f101426cb2ecc79d817a8a65928965fc860 (patch) | |
tree | 55a2b7c5ccb28ea38bf82f7d799447980e2126c7 /arch/x86/ia32 | |
parent | b359e8a434cc3d09847010fc4aeccf48d69740e4 (diff) |
x86, xsave: dynamically allocate sigframes fpstate instead of static allocation
dynamically allocate fpstate on the stack, instead of static allocation
in the current sigframe layout on the user stack. This will allow the
fpstate structure to grow in the future, which includes extended state
information supporting xsave/xrstor.
signal handlers will be able to access the fpstate pointer from the
sigcontext structure asusual, with no change. For the non RT sigframe's
(which are supported only for 32bit apps), current static fpstate layout
in the sigframe will be unused(so that we don't change the extramask[]
offset in the sigframe and thus prevent breaking app's which modify
extramask[]).
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
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) |