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