aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
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 /arch/x86/kernel
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>
Diffstat (limited to 'arch/x86/kernel')
-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
5 files changed, 32 insertions, 8 deletions
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};
21#else 30#else
22struct rt_sigframe { 31struct rt_sigframe {
23 char __user *pretcode; 32 char __user *pretcode;
24 struct ucontext uc; 33 struct ucontext uc;
25 struct siginfo info; 34 struct siginfo info;
35 /* fp state follows here */
26}; 36};
27#endif 37#endif
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 */
308static inline void __user * 308static inline void __user *
309get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) 309get_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)
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index ca316b5b742c..0deab8eff33f 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -281,7 +281,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
281 struct task_struct *me = current; 281 struct task_struct *me = current;
282 282
283 if (used_math()) { 283 if (used_math()) {
284 fp = get_stack(ka, regs, sizeof(struct _fpstate)); 284 fp = get_stack(ka, regs, sig_xstate_size);
285 frame = (void __user *)round_down( 285 frame = (void __user *)round_down(
286 (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; 286 (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8;
287 287
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index c68b7c4ca249..7ad169e33528 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -17,6 +17,10 @@ unsigned int pcntxt_hmask, pcntxt_lmask;
17 */ 17 */
18struct xsave_struct *init_xstate_buf; 18struct xsave_struct *init_xstate_buf;
19 19
20#ifdef CONFIG_X86_64
21unsigned int sig_xstate_size = sizeof(struct _fpstate);
22#endif
23
20/* 24/*
21 * Enable the extended processor state save/restore feature 25 * Enable the extended processor state save/restore feature
22 */ 26 */