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) \ 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 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 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 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 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 174 copy_fpr_to_user(void __user *to, struct task_struct *task) 175 { 176 return 0; 177 } 178 179 static inline unsigned long 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 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