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 10void __user *get_sigframe(struct ksignal *ksig, struct task_struct *tsk, 11 size_t frame_size, int is_32); 12 13extern int handle_signal32(struct ksignal *ksig, sigset_t *oldset, 14 struct task_struct *tsk); 15 16extern int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, 17 struct task_struct *tsk); 18 19static 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 35extern unsigned long copy_vsx_to_user(void __user *to, 36 struct task_struct *task); 37extern unsigned long copy_ckvsx_to_user(void __user *to, 38 struct task_struct *task); 39extern unsigned long copy_vsx_from_user(struct task_struct *task, 40 void __user *from); 41extern unsigned long copy_ckvsx_from_user(struct task_struct *task, 42 void __user *from); 43unsigned long copy_fpr_to_user(void __user *to, struct task_struct *task); 44unsigned long copy_ckfpr_to_user(void __user *to, struct task_struct *task); 45unsigned long copy_fpr_from_user(struct task_struct *task, void __user *from); 46unsigned 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 139static inline unsigned long 140copy_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 146static inline unsigned long 147copy_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 158inline 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 164static inline unsigned long 165copy_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 176static inline unsigned long 177copy_fpr_to_user(void __user *to, struct task_struct *task) 178{ 179 return 0; 180} 181 182static inline unsigned long 183copy_fpr_from_user(struct task_struct *task, void __user *from) 184{ 185 return 0; 186} 187#endif 188 189#ifdef CONFIG_PPC64 190 191extern int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, 192 struct task_struct *tsk); 193 194#else /* CONFIG_PPC64 */ 195 196static 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 204void 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