1e9564df7SGuo Ren // SPDX-License-Identifier: GPL-2.0 2e9564df7SGuo Ren 3e9564df7SGuo Ren #include <linux/signal.h> 4e9564df7SGuo Ren #include <linux/uaccess.h> 5bf241682SGuo Ren #include <linux/syscalls.h> 6bf241682SGuo Ren #include <linux/tracehook.h> 7e9564df7SGuo Ren 8e9564df7SGuo Ren #include <asm/traps.h> 9e9564df7SGuo Ren #include <asm/ucontext.h> 10e9564df7SGuo Ren #include <asm/vdso.h> 11e9564df7SGuo Ren 12e9564df7SGuo Ren #include <abi/regdef.h> 13e9564df7SGuo Ren 14e9564df7SGuo Ren #ifdef CONFIG_CPU_HAS_FPU 15e9564df7SGuo Ren #include <abi/fpu.h> 16bf241682SGuo Ren static int restore_fpu_state(struct sigcontext __user *sc) 17e9564df7SGuo Ren { 18e9564df7SGuo Ren int err = 0; 19e9564df7SGuo Ren struct user_fp user_fp; 20e9564df7SGuo Ren 21bf241682SGuo Ren err = __copy_from_user(&user_fp, &sc->sc_user_fp, sizeof(user_fp)); 22e9564df7SGuo Ren 23e9564df7SGuo Ren restore_from_user_fp(&user_fp); 24e9564df7SGuo Ren 25e9564df7SGuo Ren return err; 26e9564df7SGuo Ren } 27e9564df7SGuo Ren 28bf241682SGuo Ren static int save_fpu_state(struct sigcontext __user *sc) 29e9564df7SGuo Ren { 30e9564df7SGuo Ren struct user_fp user_fp; 31e9564df7SGuo Ren 32e9564df7SGuo Ren save_to_user_fp(&user_fp); 33e9564df7SGuo Ren 34bf241682SGuo Ren return __copy_to_user(&sc->sc_user_fp, &user_fp, sizeof(user_fp)); 35e9564df7SGuo Ren } 36e9564df7SGuo Ren #else 37bf241682SGuo Ren #define restore_fpu_state(sigcontext) (0) 38bf241682SGuo Ren #define save_fpu_state(sigcontext) (0) 39e9564df7SGuo Ren #endif 40e9564df7SGuo Ren 41e9564df7SGuo Ren struct rt_sigframe { 42*19e5e2aeSGuo Ren /* 43*19e5e2aeSGuo Ren * pad[3] is compatible with the same struct defined in 44*19e5e2aeSGuo Ren * gcc/libgcc/config/csky/linux-unwind.h 45*19e5e2aeSGuo Ren */ 46*19e5e2aeSGuo Ren int pad[3]; 47e9564df7SGuo Ren struct siginfo info; 48e9564df7SGuo Ren struct ucontext uc; 49e9564df7SGuo Ren }; 50e9564df7SGuo Ren 51bf241682SGuo Ren static long restore_sigcontext(struct pt_regs *regs, 52bf241682SGuo Ren struct sigcontext __user *sc) 53e9564df7SGuo Ren { 54e9564df7SGuo Ren int err = 0; 55e9564df7SGuo Ren 56bf241682SGuo Ren /* sc_pt_regs is structured the same as the start of pt_regs */ 57bf241682SGuo Ren err |= __copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs)); 58e9564df7SGuo Ren 59bf241682SGuo Ren /* Restore the floating-point state. */ 60e9564df7SGuo Ren err |= restore_fpu_state(sc); 61e9564df7SGuo Ren 62e9564df7SGuo Ren return err; 63e9564df7SGuo Ren } 64e9564df7SGuo Ren 65bf241682SGuo Ren SYSCALL_DEFINE0(rt_sigreturn) 66e9564df7SGuo Ren { 67e9564df7SGuo Ren struct pt_regs *regs = current_pt_regs(); 68bf241682SGuo Ren struct rt_sigframe __user *frame; 69bf241682SGuo Ren struct task_struct *task; 70bf241682SGuo Ren sigset_t set; 71bf241682SGuo Ren 72bf241682SGuo Ren /* Always make any pending restarted system calls return -EINTR */ 73bf241682SGuo Ren current->restart_block.fn = do_no_restart_syscall; 74bf241682SGuo Ren 75bf241682SGuo Ren frame = (struct rt_sigframe __user *)regs->usp; 76e9564df7SGuo Ren 7796d4f267SLinus Torvalds if (!access_ok(frame, sizeof(*frame))) 78e9564df7SGuo Ren goto badframe; 79bf241682SGuo Ren 80e9564df7SGuo Ren if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 81e9564df7SGuo Ren goto badframe; 82e9564df7SGuo Ren 83bf241682SGuo Ren set_current_blocked(&set); 84e9564df7SGuo Ren 85bf241682SGuo Ren if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 86e9564df7SGuo Ren goto badframe; 87e9564df7SGuo Ren 88bf241682SGuo Ren if (restore_altstack(&frame->uc.uc_stack)) 89bf241682SGuo Ren goto badframe; 90bf241682SGuo Ren 91bf241682SGuo Ren return regs->a0; 92e9564df7SGuo Ren 93e9564df7SGuo Ren badframe: 94bf241682SGuo Ren task = current; 95bf241682SGuo Ren force_sig(SIGSEGV, task); 96e9564df7SGuo Ren return 0; 97e9564df7SGuo Ren } 98e9564df7SGuo Ren 99bf241682SGuo Ren static int setup_sigcontext(struct rt_sigframe __user *frame, 100bf241682SGuo Ren struct pt_regs *regs) 101e9564df7SGuo Ren { 102bf241682SGuo Ren struct sigcontext __user *sc = &frame->uc.uc_mcontext; 103e9564df7SGuo Ren int err = 0; 104e9564df7SGuo Ren 105bf241682SGuo Ren err |= __copy_to_user(&sc->sc_pt_regs, regs, sizeof(struct pt_regs)); 106e9564df7SGuo Ren err |= save_fpu_state(sc); 107e9564df7SGuo Ren 108e9564df7SGuo Ren return err; 109e9564df7SGuo Ren } 110e9564df7SGuo Ren 111bf241682SGuo Ren static inline void __user *get_sigframe(struct ksignal *ksig, 112bf241682SGuo Ren struct pt_regs *regs, size_t framesize) 113e9564df7SGuo Ren { 114bf241682SGuo Ren unsigned long sp; 115bf241682SGuo Ren /* Default to using normal stack */ 116bf241682SGuo Ren sp = regs->usp; 117e9564df7SGuo Ren 118bf241682SGuo Ren /* 119bf241682SGuo Ren * If we are on the alternate signal stack and would overflow it, don't. 120bf241682SGuo Ren * Return an always-bogus address instead so we will die with SIGSEGV. 121bf241682SGuo Ren */ 122bf241682SGuo Ren if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) 123bf241682SGuo Ren return (void __user __force *)(-1UL); 124e9564df7SGuo Ren 125e9564df7SGuo Ren /* This is the X/Open sanctioned signal stack switching. */ 126bf241682SGuo Ren sp = sigsp(sp, ksig) - framesize; 127bf241682SGuo Ren 128bf241682SGuo Ren /* Align the stack frame. */ 129bf241682SGuo Ren sp &= -8UL; 130bf241682SGuo Ren 131bf241682SGuo Ren return (void __user *)sp; 132e9564df7SGuo Ren } 133e9564df7SGuo Ren 134e9564df7SGuo Ren static int 135e9564df7SGuo Ren setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) 136e9564df7SGuo Ren { 137e9564df7SGuo Ren struct rt_sigframe *frame; 138e9564df7SGuo Ren int err = 0; 139e9564df7SGuo Ren struct csky_vdso *vdso = current->mm->context.vdso; 140e9564df7SGuo Ren 141bf241682SGuo Ren frame = get_sigframe(ksig, regs, sizeof(*frame)); 142bf241682SGuo Ren if (!access_ok(frame, sizeof(*frame))) 143bf241682SGuo Ren return -EFAULT; 144e9564df7SGuo Ren 145e9564df7SGuo Ren err |= copy_siginfo_to_user(&frame->info, &ksig->info); 146e9564df7SGuo Ren 147e9564df7SGuo Ren /* Create the ucontext. */ 148e9564df7SGuo Ren err |= __put_user(0, &frame->uc.uc_flags); 149bf241682SGuo Ren err |= __put_user(NULL, &frame->uc.uc_link); 150bf241682SGuo Ren err |= __save_altstack(&frame->uc.uc_stack, regs->usp); 151bf241682SGuo Ren err |= setup_sigcontext(frame, regs); 152bf241682SGuo Ren err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 153e9564df7SGuo Ren if (err) 154bf241682SGuo Ren return -EFAULT; 155e9564df7SGuo Ren 156bf241682SGuo Ren /* Set up to return from userspace. */ 157bf241682SGuo Ren regs->lr = (unsigned long)(vdso->rt_signal_retcode); 158bf241682SGuo Ren 159bf241682SGuo Ren /* 160bf241682SGuo Ren * Set up registers for signal handler. 161bf241682SGuo Ren * Registers that we don't modify keep the value they had from 162bf241682SGuo Ren * user-space at the time we took the signal. 163bf241682SGuo Ren * We always pass siginfo and mcontext, regardless of SA_SIGINFO, 164bf241682SGuo Ren * since some things rely on this (e.g. glibc's debug/segfault.c). 165bf241682SGuo Ren */ 166e9564df7SGuo Ren regs->pc = (unsigned long)ksig->ka.sa.sa_handler; 167bf241682SGuo Ren regs->usp = (unsigned long)frame; 168bf241682SGuo Ren regs->a0 = ksig->sig; /* a0: signal number */ 169bf241682SGuo Ren regs->a1 = (unsigned long)(&(frame->info)); /* a1: siginfo pointer */ 170bf241682SGuo Ren regs->a2 = (unsigned long)(&(frame->uc)); /* a2: ucontext pointer */ 171e9564df7SGuo Ren 172e9564df7SGuo Ren return 0; 173e9564df7SGuo Ren } 174e9564df7SGuo Ren 175bf241682SGuo Ren static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) 176e9564df7SGuo Ren { 177bf241682SGuo Ren sigset_t *oldset = sigmask_to_save(); 178bf241682SGuo Ren int ret; 179e9564df7SGuo Ren 180bf241682SGuo Ren /* Are we from a system call? */ 181f4625ee0SGuo Ren if (in_syscall(regs)) { 182bf241682SGuo Ren /* Avoid additional syscall restarting via ret_from_exception */ 183f4625ee0SGuo Ren forget_syscall(regs); 184f4625ee0SGuo Ren 185bf241682SGuo Ren /* If so, check system call restarting.. */ 186bf241682SGuo Ren switch (regs->a0) { 187bf241682SGuo Ren case -ERESTART_RESTARTBLOCK: 188bf241682SGuo Ren case -ERESTARTNOHAND: 189bf241682SGuo Ren regs->a0 = -EINTR; 190bf241682SGuo Ren break; 191bf241682SGuo Ren 192bf241682SGuo Ren case -ERESTARTSYS: 193bf241682SGuo Ren if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { 194bf241682SGuo Ren regs->a0 = -EINTR; 195bf241682SGuo Ren break; 196bf241682SGuo Ren } 197bf241682SGuo Ren /* fallthrough */ 198bf241682SGuo Ren case -ERESTARTNOINTR: 199bf241682SGuo Ren regs->a0 = regs->orig_a0; 200bf241682SGuo Ren regs->pc -= TRAP0_SIZE; 201bf241682SGuo Ren break; 202bf241682SGuo Ren } 203bf241682SGuo Ren } 204bf241682SGuo Ren 205bf241682SGuo Ren /* Set up the stack frame */ 206bf241682SGuo Ren ret = setup_rt_frame(ksig, oldset, regs); 207bf241682SGuo Ren 208bf241682SGuo Ren signal_setup_done(ret, ksig, 0); 209bf241682SGuo Ren } 210bf241682SGuo Ren 211bf241682SGuo Ren static void do_signal(struct pt_regs *regs) 212bf241682SGuo Ren { 213bf241682SGuo Ren struct ksignal ksig; 214bf241682SGuo Ren 215bf241682SGuo Ren if (get_signal(&ksig)) { 216bf241682SGuo Ren /* Actually deliver the signal */ 217bf241682SGuo Ren handle_signal(&ksig, regs); 218bf241682SGuo Ren return; 219bf241682SGuo Ren } 220bf241682SGuo Ren 221bf241682SGuo Ren /* Did we come from a system call? */ 222bf241682SGuo Ren if (in_syscall(regs)) { 223bf241682SGuo Ren /* Avoid additional syscall restarting via ret_from_exception */ 224bf241682SGuo Ren forget_syscall(regs); 225bf241682SGuo Ren 226bf241682SGuo Ren /* Restart the system call - no handlers present */ 227bf241682SGuo Ren switch (regs->a0) { 228e9564df7SGuo Ren case -ERESTARTNOHAND: 229e9564df7SGuo Ren case -ERESTARTSYS: 230e9564df7SGuo Ren case -ERESTARTNOINTR: 231e9564df7SGuo Ren regs->a0 = regs->orig_a0; 232bf241682SGuo Ren regs->pc -= TRAP0_SIZE; 233e9564df7SGuo Ren break; 234e9564df7SGuo Ren case -ERESTART_RESTARTBLOCK: 235bf241682SGuo Ren regs->a0 = regs->orig_a0; 236bf241682SGuo Ren regs_syscallid(regs) = __NR_restart_syscall; 237bf241682SGuo Ren regs->pc -= TRAP0_SIZE; 238e9564df7SGuo Ren break; 239e9564df7SGuo Ren } 240e9564df7SGuo Ren } 241e9564df7SGuo Ren 242e9564df7SGuo Ren /* 243bf241682SGuo Ren * If there is no signal to deliver, we just put the saved 244e9564df7SGuo Ren * sigmask back. 245e9564df7SGuo Ren */ 246bf241682SGuo Ren restore_saved_sigmask(); 247e9564df7SGuo Ren } 248e9564df7SGuo Ren 249bf241682SGuo Ren /* 250bf241682SGuo Ren * notification of userspace execution resumption 251bf241682SGuo Ren * - triggered by the _TIF_WORK_MASK flags 252bf241682SGuo Ren */ 253bf241682SGuo Ren asmlinkage void do_notify_resume(struct pt_regs *regs, 254bf241682SGuo Ren unsigned long thread_info_flags) 255e9564df7SGuo Ren { 256bf241682SGuo Ren /* Handle pending signal delivery */ 257bf241682SGuo Ren if (thread_info_flags & _TIF_SIGPENDING) 258f4625ee0SGuo Ren do_signal(regs); 259e9564df7SGuo Ren 260bf241682SGuo Ren if (thread_info_flags & _TIF_NOTIFY_RESUME) { 261e9564df7SGuo Ren clear_thread_flag(TIF_NOTIFY_RESUME); 262e9564df7SGuo Ren tracehook_notify_resume(regs); 263e9564df7SGuo Ren } 264e9564df7SGuo Ren } 265