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
__get_user_sigset(sigset_t * dst,const sigset_t __user * src)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
copy_fpr_to_user(void __user * to,struct task_struct * task)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
copy_fpr_from_user(struct task_struct * task,void __user * from)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
copy_ckfpr_to_user(void __user * to,struct task_struct * task)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
copy_ckfpr_from_user(struct task_struct * task,void __user * from)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
copy_fpr_to_user(void __user * to,struct task_struct * task)180 copy_fpr_to_user(void __user *to, struct task_struct *task)
181 {
182 return 0;
183 }
184
185 static inline unsigned long
copy_fpr_from_user(struct task_struct * task,void __user * from)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
handle_rt_signal64(struct ksignal * ksig,sigset_t * set,struct task_struct * tsk)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 */
211