linux/arch/metag/kernel/signal.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  Copyright (C) 1991,1992  Linus Torvalds
   4 *  Copyright (C) 2005-2012  Imagination Technologies Ltd.
   5 *
   6 *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
   7 *
   8 */
   9
  10#include <linux/sched.h>
  11#include <linux/sched/task_stack.h>
  12#include <linux/mm.h>
  13#include <linux/smp.h>
  14#include <linux/kernel.h>
  15#include <linux/signal.h>
  16#include <linux/errno.h>
  17#include <linux/wait.h>
  18#include <linux/ptrace.h>
  19#include <linux/unistd.h>
  20#include <linux/stddef.h>
  21#include <linux/personality.h>
  22#include <linux/uaccess.h>
  23#include <linux/tracehook.h>
  24
  25#include <asm/ucontext.h>
  26#include <asm/cacheflush.h>
  27#include <asm/switch.h>
  28#include <asm/syscall.h>
  29#include <asm/syscalls.h>
  30
  31#define REG_FLAGS       ctx.SaveMask
  32#define REG_RETVAL      ctx.DX[0].U0
  33#define REG_SYSCALL     ctx.DX[0].U1
  34#define REG_SP          ctx.AX[0].U0
  35#define REG_ARG1        ctx.DX[3].U1
  36#define REG_ARG2        ctx.DX[3].U0
  37#define REG_ARG3        ctx.DX[2].U1
  38#define REG_PC          ctx.CurrPC
  39#define REG_RTP         ctx.DX[4].U1
  40
  41struct rt_sigframe {
  42        struct siginfo info;
  43        struct ucontext uc;
  44        unsigned long retcode[2];
  45};
  46
  47static int restore_sigcontext(struct pt_regs *regs,
  48                              struct sigcontext __user *sc)
  49{
  50        int err;
  51
  52        /* Always make any pending restarted system calls return -EINTR */
  53        current->restart_block.fn = do_no_restart_syscall;
  54
  55        err = metag_gp_regs_copyin(regs, 0, sizeof(struct user_gp_regs), NULL,
  56                                   &sc->regs);
  57        if (!err)
  58                err = metag_cb_regs_copyin(regs, 0,
  59                                           sizeof(struct user_cb_regs), NULL,
  60                                           &sc->cb);
  61        if (!err)
  62                err = metag_rp_state_copyin(regs, 0,
  63                                            sizeof(struct user_rp_state), NULL,
  64                                            &sc->rp);
  65
  66        /* This is a user-mode context. */
  67        regs->REG_FLAGS |= TBICTX_PRIV_BIT;
  68
  69        return err;
  70}
  71
  72long sys_rt_sigreturn(void)
  73{
  74        /* NOTE - Meta stack goes UPWARDS - so we wind the stack back */
  75        struct pt_regs *regs = current_pt_regs();
  76        struct rt_sigframe __user *frame;
  77        sigset_t set;
  78
  79        frame = (__force struct rt_sigframe __user *)(regs->REG_SP -
  80                                                      sizeof(*frame));
  81
  82        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
  83                goto badframe;
  84
  85        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
  86                goto badframe;
  87
  88        set_current_blocked(&set);
  89
  90        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
  91                goto badframe;
  92
  93        if (restore_altstack(&frame->uc.uc_stack))
  94                goto badframe;
  95
  96        return regs->REG_RETVAL;
  97
  98badframe:
  99        force_sig(SIGSEGV, current);
 100
 101        return 0;
 102}
 103
 104static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 105                            unsigned long mask)
 106{
 107        int err;
 108
 109        err = metag_gp_regs_copyout(regs, 0, sizeof(struct user_gp_regs), NULL,
 110                                    &sc->regs);
 111
 112        if (!err)
 113                err = metag_cb_regs_copyout(regs, 0,
 114                                            sizeof(struct user_cb_regs), NULL,
 115                                            &sc->cb);
 116        if (!err)
 117                err = metag_rp_state_copyout(regs, 0,
 118                                             sizeof(struct user_rp_state), NULL,
 119                                             &sc->rp);
 120
 121        /* OK, clear that cbuf flag in the old context, or our stored
 122         * catch buffer will be restored when we go to call the signal
 123         * handler. Also clear out the CBRP RA/RD pipe bit incase
 124         * that is pending as well!
 125         * Note that as we have already stored this context, these
 126         * flags will get restored on sigreturn to their original
 127         * state.
 128         */
 129        regs->REG_FLAGS &= ~(TBICTX_XCBF_BIT | TBICTX_CBUF_BIT |
 130                             TBICTX_CBRP_BIT);
 131
 132        /* Clear out the LSM_STEP bits in case we are in the middle of
 133         * and MSET/MGET.
 134         */
 135        regs->ctx.Flags &= ~TXSTATUS_LSM_STEP_BITS;
 136
 137        err |= __put_user(mask, &sc->oldmask);
 138
 139        return err;
 140}
 141
 142/*
 143 * Determine which stack to use..
 144 */
 145static void __user *get_sigframe(struct ksignal *ksig, unsigned long sp)
 146{
 147        sp = sigsp(sp, ksig);
 148        sp = (sp + 7) & ~7;                     /* 8byte align stack */
 149
 150        return (void __user *)sp;
 151}
 152
 153static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 154                          struct pt_regs *regs)
 155{
 156        struct rt_sigframe __user *frame;
 157        int err;
 158        unsigned long code;
 159
 160        frame = get_sigframe(ksig, regs->REG_SP);
 161        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 162                return -EFAULT;
 163
 164        err = copy_siginfo_to_user(&frame->info, &ksig->info);
 165
 166        /* Create the ucontext.  */
 167        err |= __put_user(0, &frame->uc.uc_flags);
 168        err |= __put_user(0, (unsigned long __user *)&frame->uc.uc_link);
 169        err |= __save_altstack(&frame->uc.uc_stack, regs->REG_SP);
 170        err |= setup_sigcontext(&frame->uc.uc_mcontext,
 171                                regs, set->sig[0]);
 172        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 173
 174        if (err)
 175                return -EFAULT;
 176
 177        /* Set up to return from userspace.  */
 178
 179        /* MOV D1Re0 (D1.0), #__NR_rt_sigreturn */
 180        code = 0x03000004 | (__NR_rt_sigreturn << 3);
 181        err |= __put_user(code, (unsigned long __user *)(&frame->retcode[0]));
 182
 183        /* SWITCH #__METAG_SW_SYS */
 184        code = __METAG_SW_ENCODING(SYS);
 185        err |= __put_user(code, (unsigned long __user *)(&frame->retcode[1]));
 186
 187        if (err)
 188                return -EFAULT;
 189
 190        /* Set up registers for signal handler */
 191        regs->REG_RTP = (unsigned long) frame->retcode;
 192        regs->REG_SP = (unsigned long) frame + sizeof(*frame);
 193        regs->REG_ARG1 = ksig->sig;
 194        regs->REG_ARG2 = (unsigned long) &frame->info;
 195        regs->REG_ARG3 = (unsigned long) &frame->uc;
 196        regs->REG_PC = (unsigned long) ksig->ka.sa.sa_handler;
 197
 198        pr_debug("SIG deliver (%s:%d): sp=%p pc=%08x pr=%08x\n",
 199                 current->comm, current->pid, frame, regs->REG_PC,
 200                 regs->REG_RTP);
 201
 202        /* Now pass size of 'new code' into sigtramp so we can do a more
 203         * effective cache flush - directed rather than 'full flush'.
 204         */
 205        flush_cache_sigtramp(regs->REG_RTP, sizeof(frame->retcode));
 206
 207        return 0;
 208}
 209
 210static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 211{
 212        sigset_t *oldset = sigmask_to_save();
 213        int ret;
 214
 215        /* Set up the stack frame */
 216        ret = setup_rt_frame(ksig, oldset, regs);
 217
 218        signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 219}
 220
 221 /*
 222  * Notes for Meta.
 223  * We have moved from the old 2.4.9 SH way of using syscall_nr (in the stored
 224  * context) to passing in the syscall flag on the stack.
 225  * This is because having syscall_nr in our context does not fit with TBX, and
 226  * corrupted the stack.
 227  */
 228static int do_signal(struct pt_regs *regs, int syscall)
 229{
 230        unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
 231        int restart = 0;
 232        struct ksignal ksig;
 233
 234        /*
 235         * By the end of rt_sigreturn the context describes the point that the
 236         * signal was taken (which may happen to be just before a syscall if
 237         * it's already been restarted). This should *never* be mistaken for a
 238         * system call in need of restarting.
 239         */
 240        if (syscall == __NR_rt_sigreturn)
 241                syscall = -1;
 242
 243        /* Did we come from a system call? */
 244        if (syscall >= 0) {
 245                continue_addr = regs->REG_PC;
 246                restart_addr = continue_addr - 4;
 247                retval = regs->REG_RETVAL;
 248
 249                /*
 250                 * Prepare for system call restart. We do this here so that a
 251                 * debugger will see the already changed PC.
 252                 */
 253                switch (retval) {
 254                case -ERESTART_RESTARTBLOCK:
 255                        restart = -2;
 256                case -ERESTARTNOHAND:
 257                case -ERESTARTSYS:
 258                case -ERESTARTNOINTR:
 259                        ++restart;
 260                        regs->REG_PC = restart_addr;
 261                        break;
 262                }
 263        }
 264
 265        /*
 266         * Get the signal to deliver. When running under ptrace, at this point
 267         * the debugger may change all our registers ...
 268         */
 269        get_signal(&ksig);
 270
 271        /*
 272         * Depending on the signal settings we may need to revert the decision
 273         * to restart the system call. But skip this if a debugger has chosen to
 274         * restart at a different PC.
 275         */
 276        if (regs->REG_PC != restart_addr)
 277                restart = 0;
 278        if (ksig.sig > 0) {
 279                if (unlikely(restart)) {
 280                        if (retval == -ERESTARTNOHAND
 281                            || retval == -ERESTART_RESTARTBLOCK
 282                            || (retval == -ERESTARTSYS
 283                                && !(ksig.ka.sa.sa_flags & SA_RESTART))) {
 284                                regs->REG_RETVAL = -EINTR;
 285                                regs->REG_PC = continue_addr;
 286                        }
 287                }
 288
 289                /* Whee! Actually deliver the signal.  */
 290                handle_signal(&ksig, regs);
 291                return 0;
 292        }
 293
 294        /* Handlerless -ERESTART_RESTARTBLOCK re-enters via restart_syscall */
 295        if (unlikely(restart < 0))
 296                regs->REG_SYSCALL = __NR_restart_syscall;
 297
 298        /*
 299         * If there's no signal to deliver, we just put the saved sigmask back.
 300         */
 301        restore_saved_sigmask();
 302
 303        return restart;
 304}
 305
 306int do_work_pending(struct pt_regs *regs, unsigned int thread_flags,
 307                    int syscall)
 308{
 309        do {
 310                if (likely(thread_flags & _TIF_NEED_RESCHED)) {
 311                        schedule();
 312                } else {
 313                        if (unlikely(!user_mode(regs)))
 314                                return 0;
 315                        local_irq_enable();
 316                        if (thread_flags & _TIF_SIGPENDING) {
 317                                int restart = do_signal(regs, syscall);
 318                                if (unlikely(restart)) {
 319                                        /*
 320                                         * Restart without handlers.
 321                                         * Deal with it without leaving
 322                                         * the kernel space.
 323                                         */
 324                                        return restart;
 325                                }
 326                                syscall = -1;
 327                        } else {
 328                                clear_thread_flag(TIF_NOTIFY_RESUME);
 329                                tracehook_notify_resume(regs);
 330                        }
 331                }
 332                local_irq_disable();
 333                thread_flags = current_thread_info()->flags;
 334        } while (thread_flags & _TIF_WORK_MASK);
 335        return 0;
 336}
 337