aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/signal.c')
-rw-r--r--arch/arm/kernel/signal.c93
1 files changed, 89 insertions, 4 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index e7714f367eb8..907d5a620bca 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -18,6 +18,7 @@
18#include <asm/cacheflush.h> 18#include <asm/cacheflush.h>
19#include <asm/ucontext.h> 19#include <asm/ucontext.h>
20#include <asm/unistd.h> 20#include <asm/unistd.h>
21#include <asm/vfp.h>
21 22
22#include "ptrace.h" 23#include "ptrace.h"
23#include "signal.h" 24#include "signal.h"
@@ -175,6 +176,90 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
175 176
176#endif 177#endif
177 178
179#ifdef CONFIG_VFP
180
181static int preserve_vfp_context(struct vfp_sigframe __user *frame)
182{
183 struct thread_info *thread = current_thread_info();
184 struct vfp_hard_struct *h = &thread->vfpstate.hard;
185 const unsigned long magic = VFP_MAGIC;
186 const unsigned long size = VFP_STORAGE_SIZE;
187 int err = 0;
188
189 vfp_sync_hwstate(thread);
190 __put_user_error(magic, &frame->magic, err);
191 __put_user_error(size, &frame->size, err);
192
193 /*
194 * Copy the floating point registers. There can be unused
195 * registers see asm/hwcap.h for details.
196 */
197 err |= __copy_to_user(&frame->ufp.fpregs, &h->fpregs,
198 sizeof(h->fpregs));
199 /*
200 * Copy the status and control register.
201 */
202 __put_user_error(h->fpscr, &frame->ufp.fpscr, err);
203
204 /*
205 * Copy the exception registers.
206 */
207 __put_user_error(h->fpexc, &frame->ufp_exc.fpexc, err);
208 __put_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
209 __put_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
210
211 return err ? -EFAULT : 0;
212}
213
214static int restore_vfp_context(struct vfp_sigframe __user *frame)
215{
216 struct thread_info *thread = current_thread_info();
217 struct vfp_hard_struct *h = &thread->vfpstate.hard;
218 unsigned long magic;
219 unsigned long size;
220 unsigned long fpexc;
221 int err = 0;
222
223 __get_user_error(magic, &frame->magic, err);
224 __get_user_error(size, &frame->size, err);
225
226 if (err)
227 return -EFAULT;
228 if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
229 return -EINVAL;
230
231 /*
232 * Copy the floating point registers. There can be unused
233 * registers see asm/hwcap.h for details.
234 */
235 err |= __copy_from_user(&h->fpregs, &frame->ufp.fpregs,
236 sizeof(h->fpregs));
237 /*
238 * Copy the status and control register.
239 */
240 __get_user_error(h->fpscr, &frame->ufp.fpscr, err);
241
242 /*
243 * Sanitise and restore the exception registers.
244 */
245 __get_user_error(fpexc, &frame->ufp_exc.fpexc, err);
246 /* Ensure the VFP is enabled. */
247 fpexc |= FPEXC_EN;
248 /* Ensure FPINST2 is invalid and the exception flag is cleared. */
249 fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
250 h->fpexc = fpexc;
251
252 __get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
253 __get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
254
255 if (!err)
256 vfp_flush_hwstate(thread);
257
258 return err ? -EFAULT : 0;
259}
260
261#endif
262
178/* 263/*
179 * Do a signal return; undo the signal stack. These are aligned to 64-bit. 264 * Do a signal return; undo the signal stack. These are aligned to 64-bit.
180 */ 265 */
@@ -233,8 +318,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
233 err |= restore_iwmmxt_context(&aux->iwmmxt); 318 err |= restore_iwmmxt_context(&aux->iwmmxt);
234#endif 319#endif
235#ifdef CONFIG_VFP 320#ifdef CONFIG_VFP
236// if (err == 0) 321 if (err == 0)
237// err |= vfp_restore_state(&sf->aux.vfp); 322 err |= restore_vfp_context(&aux->vfp);
238#endif 323#endif
239 324
240 return err; 325 return err;
@@ -348,8 +433,8 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
348 err |= preserve_iwmmxt_context(&aux->iwmmxt); 433 err |= preserve_iwmmxt_context(&aux->iwmmxt);
349#endif 434#endif
350#ifdef CONFIG_VFP 435#ifdef CONFIG_VFP
351// if (err == 0) 436 if (err == 0)
352// err |= vfp_save_state(&sf->aux.vfp); 437 err |= preserve_vfp_context(&aux->vfp);
353#endif 438#endif
354 __put_user_error(0, &aux->end_magic, err); 439 __put_user_error(0, &aux->end_magic, err);
355 440