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