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/signal_64.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/signal_64.c')
-rw-r--r-- | arch/x86/kernel/signal_64.c | 83 |
1 files changed, 3 insertions, 80 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 0deab8eff33f..ddf6123a55c8 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
@@ -54,69 +54,6 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | |||
54 | } | 54 | } |
55 | 55 | ||
56 | /* | 56 | /* |
57 | * Signal frame handlers. | ||
58 | */ | ||
59 | |||
60 | static inline int save_i387(struct _fpstate __user *buf) | ||
61 | { | ||
62 | struct task_struct *tsk = current; | ||
63 | int err = 0; | ||
64 | |||
65 | BUILD_BUG_ON(sizeof(struct user_i387_struct) != | ||
66 | sizeof(tsk->thread.xstate->fxsave)); | ||
67 | |||
68 | if ((unsigned long)buf % 16) | ||
69 | printk("save_i387: bad fpstate %p\n", buf); | ||
70 | |||
71 | if (!used_math()) | ||
72 | return 0; | ||
73 | clear_used_math(); /* trigger finit */ | ||
74 | if (task_thread_info(tsk)->status & TS_USEDFPU) { | ||
75 | err = save_i387_checking((struct i387_fxsave_struct __user *) | ||
76 | buf); | ||
77 | if (err) | ||
78 | return err; | ||
79 | task_thread_info(tsk)->status &= ~TS_USEDFPU; | ||
80 | stts(); | ||
81 | } else { | ||
82 | if (__copy_to_user(buf, &tsk->thread.xstate->fxsave, | ||
83 | sizeof(struct i387_fxsave_struct))) | ||
84 | return -1; | ||
85 | } | ||
86 | return 1; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * This restores directly out of user space. Exceptions are handled. | ||
91 | */ | ||
92 | static inline int restore_i387(struct _fpstate __user *buf) | ||
93 | { | ||
94 | struct task_struct *tsk = current; | ||
95 | int err; | ||
96 | |||
97 | if (!used_math()) { | ||
98 | err = init_fpu(tsk); | ||
99 | if (err) | ||
100 | return err; | ||
101 | } | ||
102 | |||
103 | if (!(task_thread_info(current)->status & TS_USEDFPU)) { | ||
104 | clts(); | ||
105 | task_thread_info(current)->status |= TS_USEDFPU; | ||
106 | } | ||
107 | err = restore_fpu_checking((__force struct i387_fxsave_struct *)buf); | ||
108 | if (unlikely(err)) { | ||
109 | /* | ||
110 | * Encountered an error while doing the restore from the | ||
111 | * user buffer, clear the fpu state. | ||
112 | */ | ||
113 | clear_fpu(tsk); | ||
114 | clear_used_math(); | ||
115 | } | ||
116 | return err; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * Do a signal return; undo the signal stack. | 57 | * Do a signal return; undo the signal stack. |
121 | */ | 58 | */ |
122 | static int | 59 | static int |
@@ -160,25 +97,11 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
160 | { | 97 | { |
161 | struct _fpstate __user * buf; | 98 | struct _fpstate __user * buf; |
162 | err |= __get_user(buf, &sc->fpstate); | 99 | err |= __get_user(buf, &sc->fpstate); |
163 | 100 | err |= restore_i387_xstate(buf); | |
164 | if (buf) { | ||
165 | if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) | ||
166 | goto badframe; | ||
167 | err |= restore_i387(buf); | ||
168 | } else { | ||
169 | struct task_struct *me = current; | ||
170 | if (used_math()) { | ||
171 | clear_fpu(me); | ||
172 | clear_used_math(); | ||
173 | } | ||
174 | } | ||
175 | } | 101 | } |
176 | 102 | ||
177 | err |= __get_user(*pax, &sc->ax); | 103 | err |= __get_user(*pax, &sc->ax); |
178 | return err; | 104 | return err; |
179 | |||
180 | badframe: | ||
181 | return 1; | ||
182 | } | 105 | } |
183 | 106 | ||
184 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | 107 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) |
@@ -276,7 +199,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
276 | sigset_t *set, struct pt_regs * regs) | 199 | sigset_t *set, struct pt_regs * regs) |
277 | { | 200 | { |
278 | struct rt_sigframe __user *frame; | 201 | struct rt_sigframe __user *frame; |
279 | struct _fpstate __user *fp = NULL; | 202 | void __user *fp = NULL; |
280 | int err = 0; | 203 | int err = 0; |
281 | struct task_struct *me = current; | 204 | struct task_struct *me = current; |
282 | 205 | ||
@@ -288,7 +211,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
288 | if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) | 211 | if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) |
289 | goto give_sigsegv; | 212 | goto give_sigsegv; |
290 | 213 | ||
291 | if (save_i387(fp) < 0) | 214 | if (save_i387_xstate(fp) < 0) |
292 | err |= -1; | 215 | err |= -1; |
293 | } else | 216 | } else |
294 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; | 217 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; |