root/arch/riscv/kernel/signal.c

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

DEFINITIONS

This source file includes following definitions.
  1. restore_fp_state
  2. save_fp_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-or-later
   2 /*
   3  * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
   4  *  Chen Liqin <liqin.chen@sunplusct.com>
   5  *  Lennox Wu <lennox.wu@sunplusct.com>
   6  * Copyright (C) 2012 Regents of the University of California
   7  */
   8 
   9 #include <linux/signal.h>
  10 #include <linux/uaccess.h>
  11 #include <linux/syscalls.h>
  12 #include <linux/tracehook.h>
  13 #include <linux/linkage.h>
  14 
  15 #include <asm/ucontext.h>
  16 #include <asm/vdso.h>
  17 #include <asm/switch_to.h>
  18 #include <asm/csr.h>
  19 
  20 #define DEBUG_SIG 0
  21 
  22 struct rt_sigframe {
  23         struct siginfo info;
  24         struct ucontext uc;
  25 };
  26 
  27 #ifdef CONFIG_FPU
  28 static long restore_fp_state(struct pt_regs *regs,
  29                              union __riscv_fp_state __user *sc_fpregs)
  30 {
  31         long err;
  32         struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
  33         size_t i;
  34 
  35         err = __copy_from_user(&current->thread.fstate, state, sizeof(*state));
  36         if (unlikely(err))
  37                 return err;
  38 
  39         fstate_restore(current, regs);
  40 
  41         /* We support no other extension state at this time. */
  42         for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
  43                 u32 value;
  44 
  45                 err = __get_user(value, &sc_fpregs->q.reserved[i]);
  46                 if (unlikely(err))
  47                         break;
  48                 if (value != 0)
  49                         return -EINVAL;
  50         }
  51 
  52         return err;
  53 }
  54 
  55 static long save_fp_state(struct pt_regs *regs,
  56                           union __riscv_fp_state __user *sc_fpregs)
  57 {
  58         long err;
  59         struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
  60         size_t i;
  61 
  62         fstate_save(current, regs);
  63         err = __copy_to_user(state, &current->thread.fstate, sizeof(*state));
  64         if (unlikely(err))
  65                 return err;
  66 
  67         /* We support no other extension state at this time. */
  68         for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
  69                 err = __put_user(0, &sc_fpregs->q.reserved[i]);
  70                 if (unlikely(err))
  71                         break;
  72         }
  73 
  74         return err;
  75 }
  76 #else
  77 #define save_fp_state(task, regs) (0)
  78 #define restore_fp_state(task, regs) (0)
  79 #endif
  80 
  81 static long restore_sigcontext(struct pt_regs *regs,
  82         struct sigcontext __user *sc)
  83 {
  84         long err;
  85         /* sc_regs is structured the same as the start of pt_regs */
  86         err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
  87         /* Restore the floating-point state. */
  88         if (has_fpu)
  89                 err |= restore_fp_state(regs, &sc->sc_fpregs);
  90         return err;
  91 }
  92 
  93 SYSCALL_DEFINE0(rt_sigreturn)
  94 {
  95         struct pt_regs *regs = current_pt_regs();
  96         struct rt_sigframe __user *frame;
  97         struct task_struct *task;
  98         sigset_t set;
  99 
 100         /* Always make any pending restarted system calls return -EINTR */
 101         current->restart_block.fn = do_no_restart_syscall;
 102 
 103         frame = (struct rt_sigframe __user *)regs->sp;
 104 
 105         if (!access_ok(frame, sizeof(*frame)))
 106                 goto badframe;
 107 
 108         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 109                 goto badframe;
 110 
 111         set_current_blocked(&set);
 112 
 113         if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 114                 goto badframe;
 115 
 116         if (restore_altstack(&frame->uc.uc_stack))
 117                 goto badframe;
 118 
 119         return regs->a0;
 120 
 121 badframe:
 122         task = current;
 123         if (show_unhandled_signals) {
 124                 pr_info_ratelimited(
 125                         "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n",
 126                         task->comm, task_pid_nr(task), __func__,
 127                         frame, (void *)regs->sepc, (void *)regs->sp);
 128         }
 129         force_sig(SIGSEGV);
 130         return 0;
 131 }
 132 
 133 static long setup_sigcontext(struct rt_sigframe __user *frame,
 134         struct pt_regs *regs)
 135 {
 136         struct sigcontext __user *sc = &frame->uc.uc_mcontext;
 137         long err;
 138         /* sc_regs is structured the same as the start of pt_regs */
 139         err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
 140         /* Save the floating-point state. */
 141         if (has_fpu)
 142                 err |= save_fp_state(regs, &sc->sc_fpregs);
 143         return err;
 144 }
 145 
 146 static inline void __user *get_sigframe(struct ksignal *ksig,
 147         struct pt_regs *regs, size_t framesize)
 148 {
 149         unsigned long sp;
 150         /* Default to using normal stack */
 151         sp = regs->sp;
 152 
 153         /*
 154          * If we are on the alternate signal stack and would overflow it, don't.
 155          * Return an always-bogus address instead so we will die with SIGSEGV.
 156          */
 157         if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
 158                 return (void __user __force *)(-1UL);
 159 
 160         /* This is the X/Open sanctioned signal stack switching. */
 161         sp = sigsp(sp, ksig) - framesize;
 162 
 163         /* Align the stack frame. */
 164         sp &= ~0xfUL;
 165 
 166         return (void __user *)sp;
 167 }
 168 
 169 
 170 static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 171         struct pt_regs *regs)
 172 {
 173         struct rt_sigframe __user *frame;
 174         long err = 0;
 175 
 176         frame = get_sigframe(ksig, regs, sizeof(*frame));
 177         if (!access_ok(frame, sizeof(*frame)))
 178                 return -EFAULT;
 179 
 180         err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 181 
 182         /* Create the ucontext. */
 183         err |= __put_user(0, &frame->uc.uc_flags);
 184         err |= __put_user(NULL, &frame->uc.uc_link);
 185         err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
 186         err |= setup_sigcontext(frame, regs);
 187         err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 188         if (err)
 189                 return -EFAULT;
 190 
 191         /* Set up to return from userspace. */
 192         regs->ra = (unsigned long)VDSO_SYMBOL(
 193                 current->mm->context.vdso, rt_sigreturn);
 194 
 195         /*
 196          * Set up registers for signal handler.
 197          * Registers that we don't modify keep the value they had from
 198          * user-space at the time we took the signal.
 199          * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
 200          * since some things rely on this (e.g. glibc's debug/segfault.c).
 201          */
 202         regs->sepc = (unsigned long)ksig->ka.sa.sa_handler;
 203         regs->sp = (unsigned long)frame;
 204         regs->a0 = ksig->sig;                     /* a0: signal number */
 205         regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */
 206         regs->a2 = (unsigned long)(&frame->uc);   /* a2: ucontext pointer */
 207 
 208 #if DEBUG_SIG
 209         pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n",
 210                 current->comm, task_pid_nr(current), ksig->sig,
 211                 (void *)regs->sepc, (void *)regs->ra, frame);
 212 #endif
 213 
 214         return 0;
 215 }
 216 
 217 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 218 {
 219         sigset_t *oldset = sigmask_to_save();
 220         int ret;
 221 
 222         /* Are we from a system call? */
 223         if (regs->scause == EXC_SYSCALL) {
 224                 /* Avoid additional syscall restarting via ret_from_exception */
 225                 regs->scause = -1UL;
 226 
 227                 /* If so, check system call restarting.. */
 228                 switch (regs->a0) {
 229                 case -ERESTART_RESTARTBLOCK:
 230                 case -ERESTARTNOHAND:
 231                         regs->a0 = -EINTR;
 232                         break;
 233 
 234                 case -ERESTARTSYS:
 235                         if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
 236                                 regs->a0 = -EINTR;
 237                                 break;
 238                         }
 239                         /* fallthrough */
 240                 case -ERESTARTNOINTR:
 241                         regs->a0 = regs->orig_a0;
 242                         regs->sepc -= 0x4;
 243                         break;
 244                 }
 245         }
 246 
 247         /* Set up the stack frame */
 248         ret = setup_rt_frame(ksig, oldset, regs);
 249 
 250         signal_setup_done(ret, ksig, 0);
 251 }
 252 
 253 static void do_signal(struct pt_regs *regs)
 254 {
 255         struct ksignal ksig;
 256 
 257         if (get_signal(&ksig)) {
 258                 /* Actually deliver the signal */
 259                 handle_signal(&ksig, regs);
 260                 return;
 261         }
 262 
 263         /* Did we come from a system call? */
 264         if (regs->scause == EXC_SYSCALL) {
 265                 /* Avoid additional syscall restarting via ret_from_exception */
 266                 regs->scause = -1UL;
 267 
 268                 /* Restart the system call - no handlers present */
 269                 switch (regs->a0) {
 270                 case -ERESTARTNOHAND:
 271                 case -ERESTARTSYS:
 272                 case -ERESTARTNOINTR:
 273                         regs->a0 = regs->orig_a0;
 274                         regs->sepc -= 0x4;
 275                         break;
 276                 case -ERESTART_RESTARTBLOCK:
 277                         regs->a0 = regs->orig_a0;
 278                         regs->a7 = __NR_restart_syscall;
 279                         regs->sepc -= 0x4;
 280                         break;
 281                 }
 282         }
 283 
 284         /*
 285          * If there is no signal to deliver, we just put the saved
 286          * sigmask back.
 287          */
 288         restore_saved_sigmask();
 289 }
 290 
 291 /*
 292  * notification of userspace execution resumption
 293  * - triggered by the _TIF_WORK_MASK flags
 294  */
 295 asmlinkage __visible void do_notify_resume(struct pt_regs *regs,
 296                                            unsigned long thread_info_flags)
 297 {
 298         /* Handle pending signal delivery */
 299         if (thread_info_flags & _TIF_SIGPENDING)
 300                 do_signal(regs);
 301 
 302         if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 303                 clear_thread_flag(TIF_NOTIFY_RESUME);
 304                 tracehook_notify_resume(regs);
 305         }
 306 }

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