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 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 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 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 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 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 180 copy_fpr_to_user(void __user *to, struct task_struct *task) 181 { 182 return 0; 183 } 184 185 static inline unsigned long 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 199 extern long sys_rt_sigreturn(void); 200 extern long sys_sigreturn(void); 201 202 static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, 203 struct task_struct *tsk) 204 { 205 return -EFAULT; 206 } 207 208 #endif /* !defined(CONFIG_PPC64) */ 209 210 void signal_fault(struct task_struct *tsk, struct pt_regs *regs, 211 const char *where, void __user *ptr); 212 213 #endif /* _POWERPC_ARCH_SIGNAL_H */ 214