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/kernel/signal_32.c | |
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/kernel/signal_32.c')
-rw-r--r-- | arch/x86/kernel/signal_32.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 6fb5bcdd8933..19a7a5669b5b 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
@@ -306,7 +306,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, | |||
306 | * Determine which stack to use.. | 306 | * Determine which stack to use.. |
307 | */ | 307 | */ |
308 | static inline void __user * | 308 | static inline void __user * |
309 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | 309 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, |
310 | struct _fpstate **fpstate) | ||
310 | { | 311 | { |
311 | unsigned long sp; | 312 | unsigned long sp; |
312 | 313 | ||
@@ -332,6 +333,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | |||
332 | sp = (unsigned long) ka->sa.sa_restorer; | 333 | sp = (unsigned long) ka->sa.sa_restorer; |
333 | } | 334 | } |
334 | 335 | ||
336 | if (used_math()) { | ||
337 | sp = sp - sig_xstate_size; | ||
338 | *fpstate = (struct _fpstate *) sp; | ||
339 | } | ||
340 | |||
335 | sp -= frame_size; | 341 | sp -= frame_size; |
336 | /* | 342 | /* |
337 | * Align the stack pointer according to the i386 ABI, | 343 | * Align the stack pointer according to the i386 ABI, |
@@ -350,8 +356,9 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
350 | void __user *restorer; | 356 | void __user *restorer; |
351 | int err = 0; | 357 | int err = 0; |
352 | int usig; | 358 | int usig; |
359 | struct _fpstate __user *fpstate = NULL; | ||
353 | 360 | ||
354 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 361 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
355 | 362 | ||
356 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 363 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
357 | goto give_sigsegv; | 364 | goto give_sigsegv; |
@@ -366,7 +373,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
366 | if (err) | 373 | if (err) |
367 | goto give_sigsegv; | 374 | goto give_sigsegv; |
368 | 375 | ||
369 | err = setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); | 376 | err = setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); |
370 | if (err) | 377 | if (err) |
371 | goto give_sigsegv; | 378 | goto give_sigsegv; |
372 | 379 | ||
@@ -427,8 +434,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
427 | void __user *restorer; | 434 | void __user *restorer; |
428 | int err = 0; | 435 | int err = 0; |
429 | int usig; | 436 | int usig; |
437 | struct _fpstate __user *fpstate = NULL; | ||
430 | 438 | ||
431 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 439 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
432 | 440 | ||
433 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 441 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
434 | goto give_sigsegv; | 442 | goto give_sigsegv; |
@@ -453,7 +461,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
453 | err |= __put_user(sas_ss_flags(regs->sp), | 461 | err |= __put_user(sas_ss_flags(regs->sp), |
454 | &frame->uc.uc_stack.ss_flags); | 462 | &frame->uc.uc_stack.ss_flags); |
455 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 463 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
456 | err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, | 464 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, |
457 | regs, set->sig[0]); | 465 | regs, set->sig[0]); |
458 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 466 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
459 | if (err) | 467 | if (err) |