diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2008-07-29 13:29:22 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-30 13:49:26 -0400 |
commit | ab5137015fed9b948fe835a2d99a4cfbd50a0c40 (patch) | |
tree | 229771c4f5606d56945941c8ada9ae6cf08d1c80 /arch/x86/kernel/i387.c | |
parent | 3c1c7f101426cb2ecc79d817a8a65928965fc860 (diff) |
x86, xsave: reorganization of signal save/restore fpstate code layout
move 64bit routines that saves/restores fpstate in/from user stack from
signal_64.c to xsave.c
restore_i387_xstate() now handles the condition when user passes
NULL fpstate.
Other misc changes for prepartion of xsave/xrstor sigcontext support.
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/i387.c')
-rw-r--r-- | arch/x86/kernel/i387.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 51fb288a2c97..7daf3a011dd9 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
@@ -21,9 +21,10 @@ | |||
21 | # include <asm/sigcontext32.h> | 21 | # include <asm/sigcontext32.h> |
22 | # include <asm/user32.h> | 22 | # include <asm/user32.h> |
23 | #else | 23 | #else |
24 | # define save_i387_ia32 save_i387 | 24 | # define save_i387_xstate_ia32 save_i387_xstate |
25 | # define restore_i387_ia32 restore_i387 | 25 | # define restore_i387_xstate_ia32 restore_i387_xstate |
26 | # define _fpstate_ia32 _fpstate | 26 | # define _fpstate_ia32 _fpstate |
27 | # define _xstate_ia32 _xstate | ||
27 | # define sig_xstate_ia32_size sig_xstate_size | 28 | # define sig_xstate_ia32_size sig_xstate_size |
28 | # define user_i387_ia32_struct user_i387_struct | 29 | # define user_i387_ia32_struct user_i387_struct |
29 | # define user32_fxsr_struct user_fxsr_struct | 30 | # define user32_fxsr_struct user_fxsr_struct |
@@ -424,7 +425,6 @@ static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf) | |||
424 | struct task_struct *tsk = current; | 425 | struct task_struct *tsk = current; |
425 | struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave; | 426 | struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave; |
426 | 427 | ||
427 | unlazy_fpu(tsk); | ||
428 | fp->status = fp->swd; | 428 | fp->status = fp->swd; |
429 | if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct))) | 429 | if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct))) |
430 | return -1; | 430 | return -1; |
@@ -438,8 +438,6 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) | |||
438 | struct user_i387_ia32_struct env; | 438 | struct user_i387_ia32_struct env; |
439 | int err = 0; | 439 | int err = 0; |
440 | 440 | ||
441 | unlazy_fpu(tsk); | ||
442 | |||
443 | convert_from_fxsr(&env, tsk); | 441 | convert_from_fxsr(&env, tsk); |
444 | if (__copy_to_user(buf, &env, sizeof(env))) | 442 | if (__copy_to_user(buf, &env, sizeof(env))) |
445 | return -1; | 443 | return -1; |
@@ -455,10 +453,16 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) | |||
455 | return 1; | 453 | return 1; |
456 | } | 454 | } |
457 | 455 | ||
458 | int save_i387_ia32(struct _fpstate_ia32 __user *buf) | 456 | int save_i387_xstate_ia32(void __user *buf) |
459 | { | 457 | { |
458 | struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; | ||
459 | struct task_struct *tsk = current; | ||
460 | |||
460 | if (!used_math()) | 461 | if (!used_math()) |
461 | return 0; | 462 | return 0; |
463 | |||
464 | if (!access_ok(VERIFY_WRITE, buf, sig_xstate_ia32_size)) | ||
465 | return -EACCES; | ||
462 | /* | 466 | /* |
463 | * This will cause a "finit" to be triggered by the next | 467 | * This will cause a "finit" to be triggered by the next |
464 | * attempted FPU operation by the 'current' process. | 468 | * attempted FPU operation by the 'current' process. |
@@ -468,13 +472,15 @@ int save_i387_ia32(struct _fpstate_ia32 __user *buf) | |||
468 | if (!HAVE_HWFP) { | 472 | if (!HAVE_HWFP) { |
469 | return fpregs_soft_get(current, NULL, | 473 | return fpregs_soft_get(current, NULL, |
470 | 0, sizeof(struct user_i387_ia32_struct), | 474 | 0, sizeof(struct user_i387_ia32_struct), |
471 | NULL, buf) ? -1 : 1; | 475 | NULL, fp) ? -1 : 1; |
472 | } | 476 | } |
473 | 477 | ||
478 | unlazy_fpu(tsk); | ||
479 | |||
474 | if (cpu_has_fxsr) | 480 | if (cpu_has_fxsr) |
475 | return save_i387_fxsave(buf); | 481 | return save_i387_fxsave(fp); |
476 | else | 482 | else |
477 | return save_i387_fsave(buf); | 483 | return save_i387_fsave(fp); |
478 | } | 484 | } |
479 | 485 | ||
480 | static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) | 486 | static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) |
@@ -502,14 +508,26 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) | |||
502 | return 0; | 508 | return 0; |
503 | } | 509 | } |
504 | 510 | ||
505 | int restore_i387_ia32(struct _fpstate_ia32 __user *buf) | 511 | int restore_i387_xstate_ia32(void __user *buf) |
506 | { | 512 | { |
507 | int err; | 513 | int err; |
508 | struct task_struct *tsk = current; | 514 | struct task_struct *tsk = current; |
515 | struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; | ||
509 | 516 | ||
510 | if (HAVE_HWFP) | 517 | if (HAVE_HWFP) |
511 | clear_fpu(tsk); | 518 | clear_fpu(tsk); |
512 | 519 | ||
520 | if (!buf) { | ||
521 | if (used_math()) { | ||
522 | clear_fpu(tsk); | ||
523 | clear_used_math(); | ||
524 | } | ||
525 | |||
526 | return 0; | ||
527 | } else | ||
528 | if (!access_ok(VERIFY_READ, buf, sig_xstate_ia32_size)) | ||
529 | return -EACCES; | ||
530 | |||
513 | if (!used_math()) { | 531 | if (!used_math()) { |
514 | err = init_fpu(tsk); | 532 | err = init_fpu(tsk); |
515 | if (err) | 533 | if (err) |
@@ -518,13 +536,13 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf) | |||
518 | 536 | ||
519 | if (HAVE_HWFP) { | 537 | if (HAVE_HWFP) { |
520 | if (cpu_has_fxsr) | 538 | if (cpu_has_fxsr) |
521 | err = restore_i387_fxsave(buf); | 539 | err = restore_i387_fxsave(fp); |
522 | else | 540 | else |
523 | err = restore_i387_fsave(buf); | 541 | err = restore_i387_fsave(fp); |
524 | } else { | 542 | } else { |
525 | err = fpregs_soft_set(current, NULL, | 543 | err = fpregs_soft_set(current, NULL, |
526 | 0, sizeof(struct user_i387_ia32_struct), | 544 | 0, sizeof(struct user_i387_ia32_struct), |
527 | NULL, buf) != 0; | 545 | NULL, fp) != 0; |
528 | } | 546 | } |
529 | set_used_math(); | 547 | set_used_math(); |
530 | 548 | ||