root/arch/csky/kernel/signal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. restore_fpu_state
  2. save_fpu_state
  3. restore_sigcontext
  4. SYSCALL_DEFINE0
  5. setup_sigcontext
  6. get_sigframe
  7. setup_rt_frame
  8. handle_signal
  9. do_signal
  10. do_notify_resume

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

/* [<][>][^][v][top][bottom][index][help] */