Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sigutil_32.c
Go to the documentation of this file.
1 #include <linux/kernel.h>
2 #include <linux/types.h>
3 #include <linux/thread_info.h>
4 #include <linux/uaccess.h>
5 #include <linux/sched.h>
6 
7 #include <asm/sigcontext.h>
8 #include <asm/fpumacro.h>
9 #include <asm/ptrace.h>
10 #include <asm/switch_to.h>
11 
12 #include "sigutil.h"
13 
15 {
16  int err = 0;
17 #ifdef CONFIG_SMP
18  if (test_tsk_thread_flag(current, TIF_USEDFPU)) {
19  put_psr(get_psr() | PSR_EF);
20  fpsave(&current->thread.float_regs[0], &current->thread.fsr,
21  &current->thread.fpqueue[0], &current->thread.fpqdepth);
22  regs->psr &= ~(PSR_EF);
23  clear_tsk_thread_flag(current, TIF_USEDFPU);
24  }
25 #else
27  put_psr(get_psr() | PSR_EF);
28  fpsave(&current->thread.float_regs[0], &current->thread.fsr,
29  &current->thread.fpqueue[0], &current->thread.fpqdepth);
31  regs->psr &= ~(PSR_EF);
32  }
33 #endif
34  err |= __copy_to_user(&fpu->si_float_regs[0],
35  &current->thread.float_regs[0],
36  (sizeof(unsigned long) * 32));
37  err |= __put_user(current->thread.fsr, &fpu->si_fsr);
38  err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
39  if (current->thread.fpqdepth != 0)
40  err |= __copy_to_user(&fpu->si_fpqueue[0],
41  &current->thread.fpqueue[0],
42  ((sizeof(unsigned long) +
43  (sizeof(unsigned long *)))*16));
45  return err;
46 }
47 
49 {
50  int err;
51 #ifdef CONFIG_SMP
52  if (test_tsk_thread_flag(current, TIF_USEDFPU))
53  regs->psr &= ~PSR_EF;
54 #else
57  regs->psr &= ~PSR_EF;
58  }
59 #endif
60  set_used_math();
61  clear_tsk_thread_flag(current, TIF_USEDFPU);
62 
63  if (!access_ok(VERIFY_READ, fpu, sizeof(*fpu)))
64  return -EFAULT;
65 
66  err = __copy_from_user(&current->thread.float_regs[0], &fpu->si_float_regs[0],
67  (sizeof(unsigned long) * 32));
68  err |= __get_user(current->thread.fsr, &fpu->si_fsr);
69  err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
70  if (current->thread.fpqdepth != 0)
71  err |= __copy_from_user(&current->thread.fpqueue[0],
72  &fpu->si_fpqueue[0],
73  ((sizeof(unsigned long) +
74  (sizeof(unsigned long *)))*16));
75  return err;
76 }
77 
78 int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
79 {
80  int i, err = __put_user(wsaved, &rwin->wsaved);
81 
82  for (i = 0; i < wsaved; i++) {
83  struct reg_window32 *rp;
84  unsigned long fp;
85 
86  rp = &current_thread_info()->reg_window[i];
87  fp = current_thread_info()->rwbuf_stkptrs[i];
88  err |= copy_to_user(&rwin->reg_window[i], rp,
89  sizeof(struct reg_window32));
90  err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
91  }
92  return err;
93 }
94 
96 {
97  struct thread_info *t = current_thread_info();
98  int i, wsaved, err;
99 
100  __get_user(wsaved, &rp->wsaved);
101  if (wsaved > NSWINS)
102  return -EFAULT;
103 
104  err = 0;
105  for (i = 0; i < wsaved; i++) {
106  err |= copy_from_user(&t->reg_window[i],
107  &rp->reg_window[i],
108  sizeof(struct reg_window32));
109  err |= __get_user(t->rwbuf_stkptrs[i],
110  &rp->rwbuf_stkptrs[i]);
111  }
112  if (err)
113  return err;
114 
115  t->w_saved = wsaved;
117  if (t->w_saved)
118  return -EFAULT;
119  return 0;
120 
121 }