xref: /openbmc/linux/arch/powerpc/kernel/signal.h (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
122e38f29SBenjamin Herrenschmidt /*
2446957baSAdam Buchbinder  *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Corporation
322e38f29SBenjamin Herrenschmidt  *    Extracted from signal_32.c and signal_64.c
422e38f29SBenjamin Herrenschmidt  *
522e38f29SBenjamin Herrenschmidt  * This file is subject to the terms and conditions of the GNU General
622e38f29SBenjamin Herrenschmidt  * Public License.  See the file README.legal in the main directory of
722e38f29SBenjamin Herrenschmidt  * this archive for more details.
822e38f29SBenjamin Herrenschmidt  */
922e38f29SBenjamin Herrenschmidt 
1022e38f29SBenjamin Herrenschmidt #ifndef _POWERPC_ARCH_SIGNAL_H
1122e38f29SBenjamin Herrenschmidt #define _POWERPC_ARCH_SIGNAL_H
1222e38f29SBenjamin Herrenschmidt 
13c180cb30SChristophe Leroy void __user *get_sigframe(struct ksignal *ksig, struct task_struct *tsk,
14efbda860SJosh Boyer 			  size_t frame_size, int is_32);
15f478f543SChristoph Hellwig 
16129b69dfSRichard Weinberger extern int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
17d1199431SCyril Bur 			   struct task_struct *tsk);
18f478f543SChristoph Hellwig 
19129b69dfSRichard Weinberger extern int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
20d1199431SCyril Bur 			      struct task_struct *tsk);
21f478f543SChristoph Hellwig 
__get_user_sigset(sigset_t * dst,const sigset_t __user * src)22d3ccc978SChristopher M. Riedl static inline int __get_user_sigset(sigset_t *dst, const sigset_t __user *src)
23d3ccc978SChristopher M. Riedl {
24d3ccc978SChristopher M. Riedl 	BUILD_BUG_ON(sizeof(sigset_t) != sizeof(u64));
25d3ccc978SChristopher M. Riedl 
26d3ccc978SChristopher M. Riedl 	return __get_user(dst->sig[0], (u64 __user *)&src->sig[0]);
27d3ccc978SChristopher M. Riedl }
28*5499802bSChristophe Leroy #define unsafe_get_user_sigset(dst, src, label) do {			\
29*5499802bSChristophe Leroy 	sigset_t *__dst = dst;						\
30*5499802bSChristophe Leroy 	const sigset_t __user *__src = src;				\
31*5499802bSChristophe Leroy 	int i;								\
32*5499802bSChristophe Leroy 									\
33*5499802bSChristophe Leroy 	for (i = 0; i < _NSIG_WORDS; i++)				\
34*5499802bSChristophe Leroy 		unsafe_get_user(__dst->sig[i], &__src->sig[i], label);	\
35*5499802bSChristophe Leroy } while (0)
36d3ccc978SChristopher M. Riedl 
376a274c08SMichael Neuling #ifdef CONFIG_VSX
386a274c08SMichael Neuling extern unsigned long copy_vsx_to_user(void __user *to,
396a274c08SMichael Neuling 				      struct task_struct *task);
40000ec280SCyril Bur extern unsigned long copy_ckvsx_to_user(void __user *to,
412b0a576dSMichael Neuling 					       struct task_struct *task);
426a274c08SMichael Neuling extern unsigned long copy_vsx_from_user(struct task_struct *task,
436a274c08SMichael Neuling 					void __user *from);
44000ec280SCyril Bur extern unsigned long copy_ckvsx_from_user(struct task_struct *task,
452b0a576dSMichael Neuling 						 void __user *from);
4695593e93SChristophe Leroy unsigned long copy_fpr_to_user(void __user *to, struct task_struct *task);
4795593e93SChristophe Leroy unsigned long copy_ckfpr_to_user(void __user *to, struct task_struct *task);
4895593e93SChristophe Leroy unsigned long copy_fpr_from_user(struct task_struct *task, void __user *from);
4995593e93SChristophe Leroy unsigned long copy_ckfpr_from_user(struct task_struct *task, void __user *from);
50b3484a1dSChristophe Leroy 
51b3484a1dSChristophe Leroy #define unsafe_copy_fpr_to_user(to, task, label)	do {		\
52b3484a1dSChristophe Leroy 	struct task_struct *__t = task;					\
53b3484a1dSChristophe Leroy 	u64 __user *buf = (u64 __user *)to;				\
54b3484a1dSChristophe Leroy 	int i;								\
55b3484a1dSChristophe Leroy 									\
56b3484a1dSChristophe Leroy 	for (i = 0; i < ELF_NFPREG - 1 ; i++)				\
57b3484a1dSChristophe Leroy 		unsafe_put_user(__t->thread.TS_FPR(i), &buf[i], label); \
58b3484a1dSChristophe Leroy 	unsafe_put_user(__t->thread.fp_state.fpscr, &buf[i], label);	\
59b3484a1dSChristophe Leroy } while (0)
60b3484a1dSChristophe Leroy 
61b3484a1dSChristophe Leroy #define unsafe_copy_vsx_to_user(to, task, label)	do {		\
62b3484a1dSChristophe Leroy 	struct task_struct *__t = task;					\
63b3484a1dSChristophe Leroy 	u64 __user *buf = (u64 __user *)to;				\
64b3484a1dSChristophe Leroy 	int i;								\
65b3484a1dSChristophe Leroy 									\
66b3484a1dSChristophe Leroy 	for (i = 0; i < ELF_NVSRHALFREG ; i++)				\
67b3484a1dSChristophe Leroy 		unsafe_put_user(__t->thread.fp_state.fpr[i][TS_VSRLOWOFFSET], \
68b3484a1dSChristophe Leroy 				&buf[i], label);\
69b3484a1dSChristophe Leroy } while (0)
70b3484a1dSChristophe Leroy 
71609355dfSChristopher M. Riedl #define unsafe_copy_fpr_from_user(task, from, label)	do {		\
72609355dfSChristopher M. Riedl 	struct task_struct *__t = task;					\
73609355dfSChristopher M. Riedl 	u64 __user *buf = (u64 __user *)from;				\
74609355dfSChristopher M. Riedl 	int i;								\
75609355dfSChristopher M. Riedl 									\
76609355dfSChristopher M. Riedl 	for (i = 0; i < ELF_NFPREG - 1; i++)				\
77609355dfSChristopher M. Riedl 		unsafe_get_user(__t->thread.TS_FPR(i), &buf[i], label); \
78609355dfSChristopher M. Riedl 	unsafe_get_user(__t->thread.fp_state.fpscr, &buf[i], label);	\
79609355dfSChristopher M. Riedl } while (0)
80609355dfSChristopher M. Riedl 
81609355dfSChristopher M. Riedl #define unsafe_copy_vsx_from_user(task, from, label)	do {		\
82609355dfSChristopher M. Riedl 	struct task_struct *__t = task;					\
83609355dfSChristopher M. Riedl 	u64 __user *buf = (u64 __user *)from;				\
84609355dfSChristopher M. Riedl 	int i;								\
85609355dfSChristopher M. Riedl 									\
86609355dfSChristopher M. Riedl 	for (i = 0; i < ELF_NVSRHALFREG ; i++)				\
87609355dfSChristopher M. Riedl 		unsafe_get_user(__t->thread.fp_state.fpr[i][TS_VSRLOWOFFSET], \
88609355dfSChristopher M. Riedl 				&buf[i], label);			\
89609355dfSChristopher M. Riedl } while (0)
90609355dfSChristopher M. Riedl 
91b3484a1dSChristophe Leroy #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
92b3484a1dSChristophe Leroy #define unsafe_copy_ckfpr_to_user(to, task, label)	do {		\
93b3484a1dSChristophe Leroy 	struct task_struct *__t = task;					\
94b3484a1dSChristophe Leroy 	u64 __user *buf = (u64 __user *)to;				\
95b3484a1dSChristophe Leroy 	int i;								\
96b3484a1dSChristophe Leroy 									\
97b3484a1dSChristophe Leroy 	for (i = 0; i < ELF_NFPREG - 1 ; i++)				\
98b3484a1dSChristophe Leroy 		unsafe_put_user(__t->thread.TS_CKFPR(i), &buf[i], label);\
99b3484a1dSChristophe Leroy 	unsafe_put_user(__t->thread.ckfp_state.fpscr, &buf[i], label);	\
100b3484a1dSChristophe Leroy } while (0)
101b3484a1dSChristophe Leroy 
102b3484a1dSChristophe Leroy #define unsafe_copy_ckvsx_to_user(to, task, label)	do {		\
103b3484a1dSChristophe Leroy 	struct task_struct *__t = task;					\
104b3484a1dSChristophe Leroy 	u64 __user *buf = (u64 __user *)to;				\
105b3484a1dSChristophe Leroy 	int i;								\
106b3484a1dSChristophe Leroy 									\
107b3484a1dSChristophe Leroy 	for (i = 0; i < ELF_NVSRHALFREG ; i++)				\
108b3484a1dSChristophe Leroy 		unsafe_put_user(__t->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET], \
109b3484a1dSChristophe Leroy 				&buf[i], label);\
110b3484a1dSChristophe Leroy } while (0)
1117c11f889SChristophe Leroy 
1127c11f889SChristophe Leroy #define unsafe_copy_ckfpr_from_user(task, from, label)	do {		\
1137c11f889SChristophe Leroy 	struct task_struct *__t = task;					\
1147c11f889SChristophe Leroy 	u64 __user *buf = (u64 __user *)from;				\
1157c11f889SChristophe Leroy 	int i;								\
1167c11f889SChristophe Leroy 									\
1177c11f889SChristophe Leroy 	for (i = 0; i < ELF_NFPREG - 1 ; i++)				\
1187c11f889SChristophe Leroy 		unsafe_get_user(__t->thread.TS_CKFPR(i), &buf[i], label);\
1197c11f889SChristophe Leroy 	unsafe_get_user(__t->thread.ckfp_state.fpscr, &buf[i], failed);	\
1207c11f889SChristophe Leroy } while (0)
1217c11f889SChristophe Leroy 
1227c11f889SChristophe Leroy #define unsafe_copy_ckvsx_from_user(task, from, label)	do {		\
1237c11f889SChristophe Leroy 	struct task_struct *__t = task;					\
1247c11f889SChristophe Leroy 	u64 __user *buf = (u64 __user *)from;				\
1257c11f889SChristophe Leroy 	int i;								\
1267c11f889SChristophe Leroy 									\
1277c11f889SChristophe Leroy 	for (i = 0; i < ELF_NVSRHALFREG ; i++)				\
1287c11f889SChristophe Leroy 		unsafe_get_user(__t->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET], \
1297c11f889SChristophe Leroy 				&buf[i], label);			\
1307c11f889SChristophe Leroy } while (0)
131b3484a1dSChristophe Leroy #endif
132b6254cedSChristophe Leroy #elif defined(CONFIG_PPC_FPU_REGS)
133b3484a1dSChristophe Leroy 
134b3484a1dSChristophe Leroy #define unsafe_copy_fpr_to_user(to, task, label)		\
135b3484a1dSChristophe Leroy 	unsafe_copy_to_user(to, (task)->thread.fp_state.fpr,	\
136b3484a1dSChristophe Leroy 			    ELF_NFPREG * sizeof(double), label)
137b3484a1dSChristophe Leroy 
138609355dfSChristopher M. Riedl #define unsafe_copy_fpr_from_user(task, from, label)			\
139609355dfSChristopher M. Riedl 	unsafe_copy_from_user((task)->thread.fp_state.fpr, from,	\
140609355dfSChristopher M. Riedl 			    ELF_NFPREG * sizeof(double), label)
141609355dfSChristopher M. Riedl 
14295593e93SChristophe Leroy static inline unsigned long
copy_fpr_to_user(void __user * to,struct task_struct * task)14395593e93SChristophe Leroy copy_fpr_to_user(void __user *to, struct task_struct *task)
14495593e93SChristophe Leroy {
14595593e93SChristophe Leroy 	return __copy_to_user(to, task->thread.fp_state.fpr,
14695593e93SChristophe Leroy 			      ELF_NFPREG * sizeof(double));
14795593e93SChristophe Leroy }
14895593e93SChristophe Leroy 
14995593e93SChristophe Leroy static inline unsigned long
copy_fpr_from_user(struct task_struct * task,void __user * from)15095593e93SChristophe Leroy copy_fpr_from_user(struct task_struct *task, void __user *from)
15195593e93SChristophe Leroy {
15295593e93SChristophe Leroy 	return __copy_from_user(task->thread.fp_state.fpr, from,
15395593e93SChristophe Leroy 			      ELF_NFPREG * sizeof(double));
15495593e93SChristophe Leroy }
15595593e93SChristophe Leroy 
15695593e93SChristophe Leroy #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
157b3484a1dSChristophe Leroy #define unsafe_copy_ckfpr_to_user(to, task, label)		\
158b3484a1dSChristophe Leroy 	unsafe_copy_to_user(to, (task)->thread.ckfp_state.fpr,	\
159b3484a1dSChristophe Leroy 			    ELF_NFPREG * sizeof(double), label)
160b3484a1dSChristophe Leroy 
copy_ckfpr_to_user(void __user * to,struct task_struct * task)16195593e93SChristophe Leroy inline unsigned long copy_ckfpr_to_user(void __user *to, struct task_struct *task)
16295593e93SChristophe Leroy {
16395593e93SChristophe Leroy 	return __copy_to_user(to, task->thread.ckfp_state.fpr,
16495593e93SChristophe Leroy 			      ELF_NFPREG * sizeof(double));
16595593e93SChristophe Leroy }
16695593e93SChristophe Leroy 
16795593e93SChristophe Leroy static inline unsigned long
copy_ckfpr_from_user(struct task_struct * task,void __user * from)16895593e93SChristophe Leroy copy_ckfpr_from_user(struct task_struct *task, void __user *from)
16995593e93SChristophe Leroy {
17095593e93SChristophe Leroy 	return __copy_from_user(task->thread.ckfp_state.fpr, from,
17195593e93SChristophe Leroy 				ELF_NFPREG * sizeof(double));
17295593e93SChristophe Leroy }
17395593e93SChristophe Leroy #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
174b6254cedSChristophe Leroy #else
175bc581dbaSChristophe Leroy #define unsafe_copy_fpr_to_user(to, task, label) do { if (0) goto label;} while (0)
176b3484a1dSChristophe Leroy 
177bc581dbaSChristophe Leroy #define unsafe_copy_fpr_from_user(task, from, label) do { if (0) goto label;} while (0)
178609355dfSChristopher M. Riedl 
179b6254cedSChristophe Leroy static inline unsigned long
copy_fpr_to_user(void __user * to,struct task_struct * task)180b6254cedSChristophe Leroy copy_fpr_to_user(void __user *to, struct task_struct *task)
181b6254cedSChristophe Leroy {
182b6254cedSChristophe Leroy 	return 0;
183b6254cedSChristophe Leroy }
184b6254cedSChristophe Leroy 
185b6254cedSChristophe Leroy static inline unsigned long
copy_fpr_from_user(struct task_struct * task,void __user * from)186b6254cedSChristophe Leroy copy_fpr_from_user(struct task_struct *task, void __user *from)
187b6254cedSChristophe Leroy {
188b6254cedSChristophe Leroy 	return 0;
189b6254cedSChristophe Leroy }
1906a274c08SMichael Neuling #endif
1912f97cd39SBenjamin Herrenschmidt 
1922f97cd39SBenjamin Herrenschmidt #ifdef CONFIG_PPC64
1932f97cd39SBenjamin Herrenschmidt 
194129b69dfSRichard Weinberger extern int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
195d1199431SCyril Bur 			      struct task_struct *tsk);
19622e38f29SBenjamin Herrenschmidt 
1972f97cd39SBenjamin Herrenschmidt #else /* CONFIG_PPC64 */
1982f97cd39SBenjamin Herrenschmidt 
handle_rt_signal64(struct ksignal * ksig,sigset_t * set,struct task_struct * tsk)199129b69dfSRichard Weinberger static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
200d1199431SCyril Bur 				     struct task_struct *tsk)
2012f97cd39SBenjamin Herrenschmidt {
2022f97cd39SBenjamin Herrenschmidt 	return -EFAULT;
2032f97cd39SBenjamin Herrenschmidt }
2042f97cd39SBenjamin Herrenschmidt 
2052f97cd39SBenjamin Herrenschmidt #endif /* !defined(CONFIG_PPC64) */
2062f97cd39SBenjamin Herrenschmidt 
2077fe8f773SChristophe Leroy void signal_fault(struct task_struct *tsk, struct pt_regs *regs,
2087fe8f773SChristophe Leroy 		  const char *where, void __user *ptr);
2097fe8f773SChristophe Leroy 
21022e38f29SBenjamin Herrenschmidt #endif  /* _POWERPC_ARCH_SIGNAL_H */
211