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