aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2008-07-29 13:29:21 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-30 13:49:25 -0400
commit3c1c7f101426cb2ecc79d817a8a65928965fc860 (patch)
tree55a2b7c5ccb28ea38bf82f7d799447980e2126c7
parentb359e8a434cc3d09847010fc4aeccf48d69740e4 (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>
-rw-r--r--arch/x86/ia32/ia32_signal.c24
-rw-r--r--arch/x86/kernel/i387.c2
-rw-r--r--arch/x86/kernel/sigframe.h14
-rw-r--r--arch/x86/kernel/signal_32.c18
-rw-r--r--arch/x86/kernel/signal_64.c2
-rw-r--r--arch/x86/kernel/xsave.c4
-rw-r--r--include/asm-x86/i387.h2
7 files changed, 50 insertions, 16 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)
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index b778e17e4b01..51fb288a2c97 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -24,6 +24,7 @@
24# define save_i387_ia32 save_i387 24# define save_i387_ia32 save_i387
25# define restore_i387_ia32 restore_i387 25# define restore_i387_ia32 restore_i387
26# define _fpstate_ia32 _fpstate 26# define _fpstate_ia32 _fpstate
27# define sig_xstate_ia32_size sig_xstate_size
27# define user_i387_ia32_struct user_i387_struct 28# define user_i387_ia32_struct user_i387_struct
28# define user32_fxsr_struct user_fxsr_struct 29# define user32_fxsr_struct user_fxsr_struct
29#endif 30#endif
@@ -36,6 +37,7 @@
36 37
37static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; 38static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu;
38unsigned int xstate_size; 39unsigned int xstate_size;
40unsigned int sig_xstate_ia32_size = sizeof(struct _fpstate_ia32);
39static struct i387_fxsave_struct fx_scratch __cpuinitdata; 41static struct i387_fxsave_struct fx_scratch __cpuinitdata;
40 42
41void __cpuinit mxcsr_feature_mask_init(void) 43void __cpuinit mxcsr_feature_mask_init(void)
diff --git a/arch/x86/kernel/sigframe.h b/arch/x86/kernel/sigframe.h
index 72bbb519d2dc..6dd7e2b70a4b 100644
--- a/arch/x86/kernel/sigframe.h
+++ b/arch/x86/kernel/sigframe.h
@@ -3,9 +3,18 @@ struct sigframe {
3 char __user *pretcode; 3 char __user *pretcode;
4 int sig; 4 int sig;
5 struct sigcontext sc; 5 struct sigcontext sc;
6 struct _fpstate fpstate; 6 /*
7 * fpstate is unused. fpstate is moved/allocated after
8 * retcode[] below. This movement allows to have the FP state and the
9 * future state extensions (xsave) stay together.
10 * And at the same time retaining the unused fpstate, prevents changing
11 * the offset of extramask[] in the sigframe and thus prevent any
12 * legacy application accessing/modifying it.
13 */
14 struct _fpstate fpstate_unused;
7 unsigned long extramask[_NSIG_WORDS-1]; 15 unsigned long extramask[_NSIG_WORDS-1];
8 char retcode[8]; 16 char retcode[8];
17 /* fp state follows here */
9}; 18};
10 19
11struct rt_sigframe { 20struct rt_sigframe {
@@ -15,13 +24,14 @@ struct rt_sigframe {
15 void __user *puc; 24 void __user *puc;
16 struct siginfo info; 25 struct siginfo info;
17 struct ucontext uc; 26 struct ucontext uc;
18 struct _fpstate fpstate;
19 char retcode[8]; 27 char retcode[8];
28 /* fp state follows here */
20}; 29};