aboutsummaryrefslogtreecommitdiffstats
path: root/arch
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
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')
-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
6 files changed, 48 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};
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 */