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