aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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};
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 */
diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h
index a6d256f4ac81..36dca8db1660 100644
--- a/include/asm-x86/i387.h
+++ b/include/asm-x86/i387.h
@@ -20,6 +20,7 @@
20#include <asm/uaccess.h> 20#include <asm/uaccess.h>
21#include <asm/xsave.h> 21#include <asm/xsave.h>
22 22
23extern unsigned int sig_xstate_size;
23extern void fpu_init(void); 24extern void fpu_init(void);
24extern void mxcsr_feature_mask_init(void); 25extern void mxcsr_feature_mask_init(void);
25extern int init_fpu(struct task_struct *child); 26extern int init_fpu(struct task_struct *child);
@@ -31,6 +32,7 @@ extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get;
31extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set; 32extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set;
32 33
33#ifdef CONFIG_IA32_EMULATION 34#ifdef CONFIG_IA32_EMULATION
35extern unsigned int sig_xstate_ia32_size;
34struct _fpstate_ia32; 36struct _fpstate_ia32;
35extern int save_i387_ia32(struct _fpstate_ia32 __user *buf); 37extern int save_i387_ia32(struct _fpstate_ia32 __user *buf);
36extern int restore_i387_ia32(struct _fpstate_ia32 __user *buf); 38extern int restore_i387_ia32(struct _fpstate_ia32 __user *buf);