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/xsave.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/xsave.c')
-rw-r--r-- | arch/x86/kernel/xsave.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 7ad169e33528..608e72d7ca64 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c | |||
@@ -12,6 +12,85 @@ | |||
12 | */ | 12 | */ |
13 | unsigned int pcntxt_hmask, pcntxt_lmask; | 13 | unsigned int pcntxt_hmask, pcntxt_lmask; |
14 | 14 | ||
15 | #ifdef CONFIG_X86_64 | ||
16 | /* | ||
17 | * Signal frame handlers. | ||
18 | */ | ||
19 | |||
20 | int save_i387_xstate(void __user *buf) | ||
21 | { | ||
22 | struct task_struct *tsk = current; | ||
23 | int err = 0; | ||
24 | |||
25 | if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size)) | ||
26 | return -EACCES; | ||
27 | |||
28 | BUILD_BUG_ON(sizeof(struct user_i387_struct) != | ||
29 | sizeof(tsk->thread.xstate->fxsave)); | ||
30 | |||
31 | if ((unsigned long)buf % 16) | ||
32 | printk("save_i387_xstate: bad fpstate %p\n", buf); | ||
33 | |||
34 | if (!used_math()) | ||
35 | return 0; | ||
36 | clear_used_math(); /* trigger finit */ | ||
37 | if (task_thread_info(tsk)->status & TS_USEDFPU) { | ||
38 | err = save_i387_checking((struct i387_fxsave_struct __user *) | ||
39 | buf); | ||
40 | if (err) | ||
41 | return err; | ||
42 | task_thread_info(tsk)->status &= ~TS_USEDFPU; | ||
43 | stts(); | ||
44 | } else { | ||
45 | if (__copy_to_user(buf, &tsk->thread.xstate->fxsave, | ||
46 | xstate_size)) | ||
47 | return -1; | ||
48 | } | ||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * This restores directly out of user space. Exceptions are handled. | ||
54 | */ | ||
55 | int restore_i387_xstate(void __user *buf) | ||
56 | { | ||
57 | struct task_struct *tsk = current; | ||
58 | int err; | ||
59 | |||
60 | if (!buf) { | ||
61 | if (used_math()) { | ||
62 | clear_fpu(tsk); | ||
63 | clear_used_math(); | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } else | ||
68 | if (!access_ok(VERIFY_READ, buf, sig_xstate_size)) | ||
69 | return -EACCES; | ||
70 | |||
71 | if (!used_math()) { | ||
72 | err = init_fpu(tsk); | ||
73 | if (err) | ||
74 | return err; | ||
75 | } | ||
76 | |||
77 | if (!(task_thread_info(current)->status & TS_USEDFPU)) { | ||
78 | clts(); | ||
79 | task_thread_info(current)->status |= TS_USEDFPU; | ||
80 | } | ||
81 | err = fxrstor_checking((__force struct i387_fxsave_struct *)buf); | ||
82 | if (unlikely(err)) { | ||
83 | /* | ||
84 | * Encountered an error while doing the restore from the | ||
85 | * user buffer, clear the fpu state. | ||
86 | */ | ||
87 | clear_fpu(tsk); | ||
88 | clear_used_math(); | ||
89 | } | ||
90 | return err; | ||
91 | } | ||
92 | #endif | ||
93 | |||
15 | /* | 94 | /* |
16 | * Represents init state for the supported extended state. | 95 | * Represents init state for the supported extended state. |
17 | */ | 96 | */ |