GNU Linux-libre 6.5.10-gnu
[releases.git] / arch / powerpc / kernel / signal.h
1 /*
2  *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Corporation
3  *    Extracted from signal_32.c and signal_64.c
4  *
5  * This file is subject to the terms and conditions of the GNU General
6  * Public License.  See the file README.legal in the main directory of
7  * this archive for more details.
8  */
9
10 #ifndef _POWERPC_ARCH_SIGNAL_H
11 #define _POWERPC_ARCH_SIGNAL_H
12
13 void __user *get_sigframe(struct ksignal *ksig, struct task_struct *tsk,
14                           size_t frame_size, int is_32);
15
16 extern int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
17                            struct task_struct *tsk);
18
19 extern int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
20                               struct task_struct *tsk);
21
22 static inline int __get_user_sigset(sigset_t *dst, const sigset_t __user *src)
23 {
24         BUILD_BUG_ON(sizeof(sigset_t) != sizeof(u64));
25
26         return __get_user(dst->sig[0], (u64 __user *)&src->sig[0]);
27 }
28 #define unsafe_get_user_sigset(dst, src, label) do {                    \
29         sigset_t *__dst = dst;                                          \
30         const sigset_t __user *__src = src;                             \
31         int i;                                                          \
32                                                                         \
33         for (i = 0; i < _NSIG_WORDS; i++)                               \
34                 unsafe_get_user(__dst->sig[i], &__src->sig[i], label);  \
35 } while (0)
36
37 #ifdef CONFIG_VSX
38 extern unsigned long copy_vsx_to_user(void __user *to,
39                                       struct task_struct *task);
40 extern unsigned long copy_ckvsx_to_user(void __user *to,
41                                                struct task_struct *task);
42 extern unsigned long copy_vsx_from_user(struct task_struct *task,
43                                         void __user *from);
44 extern unsigned long copy_ckvsx_from_user(struct task_struct *task,
45                                                  void __user *from);
46 unsigned long copy_fpr_to_user(void __user *to, struct task_struct *task);
47 unsigned long copy_ckfpr_to_user(void __user *to, struct task_struct *task);
48 unsigned long copy_fpr_from_user(struct task_struct *task, void __user *from);
49 unsigned long copy_ckfpr_from_user(struct task_struct *task, void __user *from);
50
51 #define unsafe_copy_fpr_to_user(to, task, label)        do {            \
52         struct task_struct *__t = task;                                 \
53         u64 __user *buf = (u64 __user *)to;                             \
54         int i;                                                          \
55                                                                         \
56         for (i = 0; i < ELF_NFPREG - 1 ; i++)                           \
57                 unsafe_put_user(__t->thread.TS_FPR(i), &buf[i], label); \
58         unsafe_put_user(__t->thread.fp_state.fpscr, &buf[i], label);    \
59 } while (0)
60
61 #define unsafe_copy_vsx_to_user(to, task, label)        do {            \
62         struct task_struct *__t = task;                                 \
63         u64 __user *buf = (u64 __user *)to;                             \
64         int i;                                                          \
65                                                                         \
66         for (i = 0; i < ELF_NVSRHALFREG ; i++)                          \
67                 unsafe_put_user(__t->thread.fp_state.fpr[i][TS_VSRLOWOFFSET], \
68                                 &buf[i], label);\
69 } while (0)
70
71 #define unsafe_copy_fpr_from_user(task, from, label)    do {            \
72         struct task_struct *__t = task;                                 \
73         u64 __user *buf = (u64 __user *)from;                           \
74         int i;                                                          \
75                                                                         \
76         for (i = 0; i < ELF_NFPREG - 1; i++)                            \
77                 unsafe_get_user(__t->thread.TS_FPR(i), &buf[i], label); \
78         unsafe_get_user(__t->thread.fp_state.fpscr, &buf[i], label);    \
79 } while (0)
80
81 #define unsafe_copy_vsx_from_user(task, from, label)    do {            \
82         struct task_struct *__t = task;                                 \
83         u64 __user *buf = (u64 __user *)from;                           \
84         int i;                                                          \
85                                                                         \
86         for (i = 0; i < ELF_NVSRHALFREG ; i++)                          \
87                 unsafe_get_user(__t->thread.fp_state.fpr[i][TS_VSRLOWOFFSET], \
88                                 &buf[i], label);                        \
89 } while (0)
90
91 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
92 #define unsafe_copy_ckfpr_to_user(to, task, label)      do {            \
93         struct task_struct *__t = task;                                 \
94         u64 __user *buf = (u64 __user *)to;                             \
95         int i;                                                          \
96                                                                         \
97         for (i = 0; i < ELF_NFPREG - 1 ; i++)                           \
98                 unsafe_put_user(__t->thread.TS_CKFPR(i), &buf[i], label);\
99         unsafe_put_user(__t->thread.ckfp_state.fpscr, &buf[i], label);  \
100 } while (0)
101
102 #define unsafe_copy_ckvsx_to_user(to, task, label)      do {            \
103         struct task_struct *__t = task;                                 \
104         u64 __user *buf = (u64 __user *)to;                             \
105         int i;                                                          \
106                                                                         \
107         for (i = 0; i < ELF_NVSRHALFREG ; i++)                          \
108                 unsafe_put_user(__t->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET], \
109                                 &buf[i], label);\
110 } while (0)
111
112 #define unsafe_copy_ckfpr_from_user(task, from, label)  do {            \
113         struct task_struct *__t = task;                                 \
114         u64 __user *buf = (u64 __user *)from;                           \
115         int i;                                                          \
116                                                                         \
117         for (i = 0; i < ELF_NFPREG - 1 ; i++)                           \
118                 unsafe_get_user(__t->thread.TS_CKFPR(i), &buf[i], label);\
119         unsafe_get_user(__t->thread.ckfp_state.fpscr, &buf[i], failed); \
120 } while (0)
121
122 #define unsafe_copy_ckvsx_from_user(task, from, label)  do {            \
123         struct task_struct *__t = task;                                 \
124         u64 __user *buf = (u64 __user *)from;                           \
125         int i;                                                          \
126                                                                         \
127         for (i = 0; i < ELF_NVSRHALFREG ; i++)                          \
128                 unsafe_get_user(__t->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET], \
129                                 &buf[i], label);                        \
130 } while (0)
131 #endif
132 #elif defined(CONFIG_PPC_FPU_REGS)
133
134 #define unsafe_copy_fpr_to_user(to, task, label)                \
135         unsafe_copy_to_user(to, (task)->thread.fp_state.fpr,    \
136                             ELF_NFPREG * sizeof(double), label)
137
138 #define unsafe_copy_fpr_from_user(task, from, label)                    \
139         unsafe_copy_from_user((task)->thread.fp_state.fpr, from,        \
140                             ELF_NFPREG * sizeof(double), label)
141
142 static inline unsigned long
143 copy_fpr_to_user(void __user *to, struct task_struct *task)
144 {
145         return __copy_to_user(to, task->thread.fp_state.fpr,
146                               ELF_NFPREG * sizeof(double));
147 }
148
149 static inline unsigned long
150 copy_fpr_from_user(struct task_struct *task, void __user *from)
151 {
152         return __copy_from_user(task->thread.fp_state.fpr, from,
153                               ELF_NFPREG * sizeof(double));
154 }
155
156 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
157 #define unsafe_copy_ckfpr_to_user(to, task, label)              \
158         unsafe_copy_to_user(to, (task)->thread.ckfp_state.fpr,  \
159                             ELF_NFPREG * sizeof(double), label)
160
161 inline unsigned long copy_ckfpr_to_user(void __user *to, struct task_struct *task)
162 {
163         return __copy_to_user(to, task->thread.ckfp_state.fpr,
164                               ELF_NFPREG * sizeof(double));
165 }
166
167 static inline unsigned long
168 copy_ckfpr_from_user(struct task_struct *task, void __user *from)
169 {
170         return __copy_from_user(task->thread.ckfp_state.fpr, from,
171                                 ELF_NFPREG * sizeof(double));
172 }
173 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
174 #else
175 #define unsafe_copy_fpr_to_user(to, task, label) do { if (0) goto label;} while (0)
176
177 #define unsafe_copy_fpr_from_user(task, from, label) do { if (0) goto label;} while (0)
178
179 static inline unsigned long
180 copy_fpr_to_user(void __user *to, struct task_struct *task)
181 {
182         return 0;
183 }
184
185 static inline unsigned long
186 copy_fpr_from_user(struct task_struct *task, void __user *from)
187 {
188         return 0;
189 }
190 #endif
191
192 #ifdef CONFIG_PPC64
193
194 extern int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
195                               struct task_struct *tsk);
196
197 #else /* CONFIG_PPC64 */
198
199 static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
200                                      struct task_struct *tsk)
201 {
202         return -EFAULT;
203 }
204
205 #endif /* !defined(CONFIG_PPC64) */
206
207 void signal_fault(struct task_struct *tsk, struct pt_regs *regs,
208                   const char *where, void __user *ptr);
209
210 #endif  /* _POWERPC_ARCH_SIGNAL_H */