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) \
29 	unsafe_get_user((dst)->sig[0], (u64 __user *)&(src)->sig[0], label)
30 
31 #ifdef CONFIG_VSX
32 extern unsigned long copy_vsx_to_user(void __user *to,
33 				      struct task_struct *task);
34 extern unsigned long copy_ckvsx_to_user(void __user *to,
35 					       struct task_struct *task);
36 extern unsigned long copy_vsx_from_user(struct task_struct *task,
37 					void __user *from);
38 extern unsigned long copy_ckvsx_from_user(struct task_struct *task,
39 						 void __user *from);
40 unsigned long copy_fpr_to_user(void __user *to, struct task_struct *task);
41 unsigned long copy_ckfpr_to_user(void __user *to, struct task_struct *task);
42 unsigned long copy_fpr_from_user(struct task_struct *task, void __user *from);
43 unsigned long copy_ckfpr_from_user(struct task_struct *task, void __user *from);
44 
45 #define unsafe_copy_fpr_to_user(to, task, label)	do {		\
46 	struct task_struct *__t = task;					\
47 	u64 __user *buf = (u64 __user *)to;				\
48 	int i;								\
49 									\
50 	for (i = 0; i < ELF_NFPREG - 1 ; i++)				\
51 		unsafe_put_user(__t->thread.TS_FPR(i), &buf[i], label); \
52 	unsafe_put_user(__t->thread.fp_state.fpscr, &buf[i], label);	\
53 } while (0)
54 
55 #define unsafe_copy_vsx_to_user(to, task, label)	do {		\
56 	struct task_struct *__t = task;					\
57 	u64 __user *buf = (u64 __user *)to;				\
58 	int i;								\
59 									\
60 	for (i = 0; i < ELF_NVSRHALFREG ; i++)				\
61 		unsafe_put_user(__t->thread.fp_state.fpr[i][TS_VSRLOWOFFSET], \
62 				&buf[i], label);\
63 } while (0)
64 
65 #define unsafe_copy_fpr_from_user(task, from, label)	do {		\
66 	struct task_struct *__t = task;					\
67 	u64 __user *buf = (u64 __user *)from;				\
68 	int i;								\
69 									\
70 	for (i = 0; i < ELF_NFPREG - 1; i++)				\
71 		unsafe_get_user(__t->thread.TS_FPR(i), &buf[i], label); \
72 	unsafe_get_user(__t->thread.fp_state.fpscr, &buf[i], label);	\
73 } while (0)
74 
75 #define unsafe_copy_vsx_from_user(task, from, label)	do {		\
76 	struct task_struct *__t = task;					\
77 	u64 __user *buf = (u64 __user *)from;				\
78 	int i;								\
79 									\
80 	for (i = 0; i < ELF_NVSRHALFREG ; i++)				\
81 		unsafe_get_user(__t->thread.fp_state.fpr[i][TS_VSRLOWOFFSET], \
82 				&buf[i], label);			\
83 } while (0)
84 
85 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
86 #define unsafe_copy_ckfpr_to_user(to, task, label)	do {		\
87 	struct task_struct *__t = task;					\
88 	u64 __user *buf = (u64 __user *)to;				\
89 	int i;								\
90 									\
91 	for (i = 0; i < ELF_NFPREG - 1 ; i++)				\
92 		unsafe_put_user(__t->thread.TS_CKFPR(i), &buf[i], label);\
93 	unsafe_put_user(__t->thread.ckfp_state.fpscr, &buf[i], label);	\
94 } while (0)
95 
96 #define unsafe_copy_ckvsx_to_user(to, task, label)	do {		\
97 	struct task_struct *__t = task;					\
98 	u64 __user *buf = (u64 __user *)to;				\
99 	int i;								\
100 									\
101 	for (i = 0; i < ELF_NVSRHALFREG ; i++)				\
102 		unsafe_put_user(__t->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET], \
103 				&buf[i], label);\
104 } while (0)
105 
106 #define unsafe_copy_ckfpr_from_user(task, from, label)	do {		\
107 	struct task_struct *__t = task;					\
108 	u64 __user *buf = (u64 __user *)from;				\
109 	int i;								\
110 									\
111 	for (i = 0; i < ELF_NFPREG - 1 ; i++)				\
112 		unsafe_get_user(__t->thread.TS_CKFPR(i), &buf[i], label);\
113 	unsafe_get_user(__t->thread.ckfp_state.fpscr, &buf[i], failed);	\
114 } while (0)
115 
116 #define unsafe_copy_ckvsx_from_user(task, from, label)	do {		\
117 	struct task_struct *__t = task;					\
118 	u64 __user *buf = (u64 __user *)from;				\
119 	int i;								\
120 									\
121 	for (i = 0; i < ELF_NVSRHALFREG ; i++)				\
122 		unsafe_get_user(__t->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET], \
123 				&buf[i], label);			\
124 } while (0)
125 #endif
126 #elif defined(CONFIG_PPC_FPU_REGS)
127 
128 #define unsafe_copy_fpr_to_user(to, task, label)		\
129 	unsafe_copy_to_user(to, (task)->thread.fp_state.fpr,	\
130 			    ELF_NFPREG * sizeof(double), label)
131 
132 #define unsafe_copy_fpr_from_user(task, from, label)			\
133 	unsafe_copy_from_user((task)->thread.fp_state.fpr, from,	\
134 			    ELF_NFPREG * sizeof(double), label)
135 
136 static inline unsigned long
copy_fpr_to_user(void __user * to,struct task_struct * task)137 copy_fpr_to_user(void __user *to, struct task_struct *task)
138 {
139 	return __copy_to_user(to, task->thread.fp_state.fpr,
140 			      ELF_NFPREG * sizeof(double));
141 }
142 
143 static inline unsigned long
copy_fpr_from_user(struct task_struct * task,void __user * from)144 copy_fpr_from_user(struct task_struct *task, void __user *from)
145 {
146 	return __copy_from_user(task->thread.fp_state.fpr, from,
147 			      ELF_NFPREG * sizeof(double));
148 }
149 
150 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
151 #define unsafe_copy_ckfpr_to_user(to, task, label)		\
152 	unsafe_copy_to_user(to, (task)->thread.ckfp_state.fpr,	\
153 			    ELF_NFPREG * sizeof(double), label)
154 
copy_ckfpr_to_user(void __user * to,struct task_struct * task)155 inline unsigned long copy_ckfpr_to_user(void __user *to, struct task_struct *task)
156 {
157 	return __copy_to_user(to, task->thread.ckfp_state.fpr,
158 			      ELF_NFPREG * sizeof(double));
159 }
160 
161 static inline unsigned long
copy_ckfpr_from_user(struct task_struct * task,void __user * from)162 copy_ckfpr_from_user(struct task_struct *task, void __user *from)
163 {
164 	return __copy_from_user(task->thread.ckfp_state.fpr, from,
165 				ELF_NFPREG * sizeof(double));
166 }
167 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
168 #else
169 #define unsafe_copy_fpr_to_user(to, task, label) do { if (0) goto label;} while (0)
170 
171 #define unsafe_copy_fpr_from_user(task, from, label) do { if (0) goto label;} while (0)
172 
173 static inline unsigned long
copy_fpr_to_user(void __user * to,struct task_struct * task)174 copy_fpr_to_user(void __user *to, struct task_struct *task)
175 {
176 	return 0;
177 }
178 
179 static inline unsigned long
copy_fpr_from_user(struct task_struct * task,void __user * from)180 copy_fpr_from_user(struct task_struct *task, void __user *from)
181 {
182 	return 0;
183 }
184 #endif
185 
186 #ifdef CONFIG_PPC64
187 
188 extern int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
189 			      struct task_struct *tsk);
190 
191 #else /* CONFIG_PPC64 */
192 
193 extern long sys_rt_sigreturn(void);
194 extern long sys_sigreturn(void);
195 
handle_rt_signal64(struct ksignal * ksig,sigset_t * set,struct task_struct * tsk)196 static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
197 				     struct task_struct *tsk)
198 {
199 	return -EFAULT;
200 }
201 
202 #endif /* !defined(CONFIG_PPC64) */
203 
204 void signal_fault(struct task_struct *tsk, struct pt_regs *regs,
205 		  const char *where, void __user *ptr);
206 
207 #endif  /* _POWERPC_ARCH_SIGNAL_H */
208