linux/arch/mn10300/kernel/signal.c
<<
>>
Prefs
   1/* MN10300 Signal handling
   2 *
   3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public Licence
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the Licence, or (at your option) any later version.
  10 */
  11
  12#include <linux/sched.h>
  13#include <linux/mm.h>
  14#include <linux/smp.h>
  15#include <linux/smp_lock.h>
  16#include <linux/kernel.h>
  17#include <linux/signal.h>
  18#include <linux/errno.h>
  19#include <linux/wait.h>
  20#include <linux/ptrace.h>
  21#include <linux/unistd.h>
  22#include <linux/stddef.h>
  23#include <linux/tty.h>
  24#include <linux/personality.h>
  25#include <linux/suspend.h>
  26#include <asm/cacheflush.h>
  27#include <asm/ucontext.h>
  28#include <asm/uaccess.h>
  29#include <asm/fpu.h>
  30#include "sigframe.h"
  31
  32#define DEBUG_SIG 0
  33
  34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
  35
  36/*
  37 * atomically swap in the new signal mask, and wait for a signal.
  38 */
  39asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
  40{
  41        mask &= _BLOCKABLE;
  42        spin_lock_irq(&current->sighand->siglock);
  43        current->saved_sigmask = current->blocked;
  44        siginitset(&current->blocked, mask);
  45        recalc_sigpending();
  46        spin_unlock_irq(&current->sighand->siglock);
  47
  48        current->state = TASK_INTERRUPTIBLE;
  49        schedule();
  50        set_thread_flag(TIF_RESTORE_SIGMASK);
  51        return -ERESTARTNOHAND;
  52}
  53
  54/*
  55 * set signal action syscall
  56 */
  57asmlinkage long sys_sigaction(int sig,
  58                              const struct old_sigaction __user *act,
  59                              struct old_sigaction __user *oact)
  60{
  61        struct k_sigaction new_ka, old_ka;
  62        int ret;
  63
  64        if (act) {
  65                old_sigset_t mask;
  66                if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
  67                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
  68                    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
  69                        return -EFAULT;
  70                __get_user(new_ka.sa.sa_flags, &act->sa_flags);
  71                __get_user(mask, &act->sa_mask);
  72                siginitset(&new_ka.sa.sa_mask, mask);
  73        }
  74
  75        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
  76
  77        if (!ret && oact) {
  78                if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
  79                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
  80                    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
  81                        return -EFAULT;
  82                __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
  83                __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
  84        }
  85
  86        return ret;
  87}
  88
  89/*
  90 * set alternate signal stack syscall
  91 */
  92asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss)
  93{
  94        return do_sigaltstack(uss, uoss, __frame->sp);
  95}
  96
  97/*
  98 * do a signal return; undo the signal stack.
  99 */
 100static int restore_sigcontext(struct pt_regs *regs,
 101                              struct sigcontext __user *sc, long *_d0)
 102{
 103        unsigned int err = 0;
 104
 105        if (is_using_fpu(current))
 106                fpu_kill_state(current);
 107
 108#define COPY(x) err |= __get_user(regs->x, &sc->x)
 109        COPY(d1); COPY(d2); COPY(d3);
 110        COPY(a0); COPY(a1); COPY(a2); COPY(a3);
 111        COPY(e0); COPY(e1); COPY(e2); COPY(e3);
 112        COPY(e4); COPY(e5); COPY(e6); COPY(e7);
 113        COPY(lar); COPY(lir);
 114        COPY(mdr); COPY(mdrq);
 115        COPY(mcvf); COPY(mcrl); COPY(mcrh);
 116        COPY(sp); COPY(pc);
 117#undef COPY
 118
 119        {
 120                unsigned int tmpflags;
 121#ifndef CONFIG_MN10300_USING_JTAG
 122#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \
 123                   EPSW_T | EPSW_nAR)
 124#else
 125#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \
 126                   EPSW_nAR)
 127#endif
 128                err |= __get_user(tmpflags, &sc->epsw);
 129                regs->epsw = (regs->epsw & ~USER_EPSW) |
 130                  (tmpflags & USER_EPSW);
 131                regs->orig_d0 = -1;             /* disable syscall checks */
 132        }
 133
 134        {
 135                struct fpucontext *buf;
 136                err |= __get_user(buf, &sc->fpucontext);
 137                if (buf) {
 138                        if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
 139                                goto badframe;
 140                        err |= fpu_restore_sigcontext(buf);
 141                }
 142        }
 143
 144        err |= __get_user(*_d0, &sc->d0);
 145        return err;
 146
 147badframe:
 148        return 1;
 149}
 150
 151/*
 152 * standard signal return syscall
 153 */
 154asmlinkage long sys_sigreturn(void)
 155{
 156        struct sigframe __user *frame = (struct sigframe __user *) __frame->sp;
 157        sigset_t set;
 158        long d0;
 159
 160        if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 161                goto badframe;
 162        if (__get_user(set.sig[0], &frame->sc.oldmask))
 163                goto badframe;
 164
 165        if (_NSIG_WORDS > 1 &&
 166            __copy_from_user(&set.sig[1], &frame->extramask,
 167                             sizeof(frame->extramask)))
 168                goto badframe;
 169
 170        sigdelsetmask(&set, ~_BLOCKABLE);
 171        spin_lock_irq(&current->sighand->siglock);
 172        current->blocked = set;
 173        recalc_sigpending();
 174        spin_unlock_irq(&current->sighand->siglock);
 175
 176        if (restore_sigcontext(__frame, &frame->sc, &d0))
 177                goto badframe;
 178
 179        return d0;
 180
 181badframe:
 182        force_sig(SIGSEGV, current);
 183        return 0;
 184}
 185
 186/*
 187 * realtime signal return syscall
 188 */
 189asmlinkage long sys_rt_sigreturn(void)
 190{
 191        struct rt_sigframe __user *frame =
 192                (struct rt_sigframe __user *) __frame->sp;
 193        sigset_t set;
 194        unsigned long d0;
 195
 196        if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 197                goto badframe;
 198        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 199                goto badframe;
 200
 201        sigdelsetmask(&set, ~_BLOCKABLE);
 202        spin_lock_irq(&current->sighand->siglock);
 203        current->blocked = set;
 204        recalc_sigpending();
 205        spin_unlock_irq(&current->sighand->siglock);
 206
 207        if (restore_sigcontext(__frame, &frame->uc.uc_mcontext, &d0))
 208                goto badframe;
 209
 210        if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT)
 211                goto badframe;
 212
 213        return d0;
 214
 215badframe:
 216        force_sig(SIGSEGV, current);
 217        return 0;
 218}
 219
 220/*
 221 * store the userspace context into a signal frame
 222 */
 223static int setup_sigcontext(struct sigcontext __user *sc,
 224                            struct fpucontext *fpuctx,
 225                            struct pt_regs *regs,
 226                            unsigned long mask)
 227{
 228        int tmp, err = 0;
 229
 230#define COPY(x) err |= __put_user(regs->x, &sc->x)
 231        COPY(d0); COPY(d1); COPY(d2); COPY(d3);
 232        COPY(a0); COPY(a1); COPY(a2); COPY(a3);
 233        COPY(e0); COPY(e1); COPY(e2); COPY(e3);
 234        COPY(e4); COPY(e5); COPY(e6); COPY(e7);
 235        COPY(lar); COPY(lir);
 236        COPY(mdr); COPY(mdrq);
 237        COPY(mcvf); COPY(mcrl); COPY(mcrh);
 238        COPY(sp); COPY(epsw); COPY(pc);
 239#undef COPY
 240
 241        tmp = fpu_setup_sigcontext(fpuctx);
 242        if (tmp < 0)
 243                err = 1;
 244        else
 245                err |= __put_user(tmp ? fpuctx : NULL, &sc->fpucontext);
 246
 247        /* non-iBCS2 extensions.. */
 248        err |= __put_user(mask, &sc->oldmask);
 249
 250        return err;
 251}
 252
 253/*
 254 * determine which stack to use..
 255 */
 256static inline void __user *get_sigframe(struct k_sigaction *ka,
 257                                        struct pt_regs *regs,
 258                                        size_t frame_size)
 259{
 260        unsigned long sp;
 261
 262        /* default to using normal stack */
 263        sp = regs->sp;
 264
 265        /* this is the X/Open sanctioned signal stack switching.  */
 266        if (ka->sa.sa_flags & SA_ONSTACK) {
 267                if (!on_sig_stack(sp))
 268                        sp = current->sas_ss_sp + current->sas_ss_size;
 269        }
 270
 271        return (void __user *) ((sp - frame_size) & ~7UL);
 272}
 273
 274/*
 275 * set up a normal signal frame
 276 */
 277static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 278                       struct pt_regs *regs)
 279{
 280        struct sigframe __user *frame;
 281        int rsig;
 282
 283        frame = get_sigframe(ka, regs, sizeof(*frame));
 284
 285        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 286                goto give_sigsegv;
 287
 288        rsig = sig;
 289        if (sig < 32 &&
 290            current_thread_info()->exec_domain &&
 291            current_thread_info()->exec_domain->signal_invmap)
 292                rsig = current_thread_info()->exec_domain->signal_invmap[sig];
 293
 294        if (__put_user(rsig, &frame->sig) < 0 ||
 295            __put_user(&frame->sc, &frame->psc) < 0)
 296                goto give_sigsegv;
 297
 298        if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0]))
 299                goto give_sigsegv;
 300
 301        if (_NSIG_WORDS > 1) {
 302                if (__copy_to_user(frame->extramask, &set->sig[1],
 303                                   sizeof(frame->extramask)))
 304                        goto give_sigsegv;
 305        }
 306
 307        /* set up to return from userspace.  If provided, use a stub already in
 308         * userspace */
 309        if (ka->sa.sa_flags & SA_RESTORER) {
 310                if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
 311                        goto give_sigsegv;
 312        } else {
 313                if (__put_user((void (*)(void))frame->retcode,
 314                               &frame->pretcode))
 315                        goto give_sigsegv;
 316                /* this is mov $,d0; syscall 0 */
 317                if (__put_user(0x2c, (char *)(frame->retcode + 0)) ||
 318                    __put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) ||
 319                    __put_user(0x00, (char *)(frame->retcode + 2)) ||
 320                    __put_user(0xf0, (char *)(frame->retcode + 3)) ||
 321                    __put_user(0xe0, (char *)(frame->retcode + 4)))
 322                        goto give_sigsegv;
 323                flush_icache_range((unsigned long) frame->retcode,
 324                                   (unsigned long) frame->retcode + 5);
 325        }
 326
 327        /* set up registers for signal handler */
 328        regs->sp = (unsigned long) frame;
 329        regs->pc = (unsigned long) ka->sa.sa_handler;
 330        regs->d0 = sig;
 331        regs->d1 = (unsigned long) &frame->sc;
 332
 333        set_fs(USER_DS);
 334
 335        /* the tracer may want to single-step inside the handler */
 336        if (test_thread_flag(TIF_SINGLESTEP))
 337                ptrace_notify(SIGTRAP);
 338
 339#if DEBUG_SIG
 340        printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
 341               sig, current->comm, current->pid, frame, regs->pc,
 342               frame->pretcode);
 343#endif
 344
 345        return 0;
 346
 347give_sigsegv:
 348        force_sig(SIGSEGV, current);
 349        return -EFAULT;
 350}
 351
 352/*
 353 * set up a realtime signal frame
 354 */
 355static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 356                          sigset_t *set, struct pt_regs *regs)
 357{
 358        struct rt_sigframe __user *frame;
 359        int rsig;
 360
 361        frame = get_sigframe(ka, regs, sizeof(*frame));
 362
 363        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 364                goto give_sigsegv;
 365
 366        rsig = sig;
 367        if (sig < 32 &&
 368            current_thread_info()->exec_domain &&
 369            current_thread_info()->exec_domain->signal_invmap)
 370                rsig = current_thread_info()->exec_domain->signal_invmap[sig];
 371
 372        if (__put_user(rsig, &frame->sig) ||
 373            __put_user(&frame->info, &frame->pinfo) ||
 374            __put_user(&frame->uc, &frame->puc) ||
 375            copy_siginfo_to_user(&frame->info, info))
 376                goto give_sigsegv;
 377
 378        /* create the ucontext.  */
 379        if (__put_user(0, &frame->uc.uc_flags) ||
 380            __put_user(0, &frame->uc.uc_link) ||
 381            __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
 382            __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) ||
 383            __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size) ||
 384            setup_sigcontext(&frame->uc.uc_mcontext,
 385                             &frame->fpuctx, regs, set->sig[0]) ||
 386            __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
 387                goto give_sigsegv;
 388
 389        /* set up to return from userspace.  If provided, use a stub already in
 390         * userspace */
 391        if (ka->sa.sa_flags & SA_RESTORER) {
 392                if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
 393                        goto give_sigsegv;
 394        } else {
 395                if (__put_user((void(*)(void))frame->retcode,
 396                               &frame->pretcode) ||
 397                    /* This is mov $,d0; syscall 0 */
 398                    __put_user(0x2c, (char *)(frame->retcode + 0)) ||
 399                    __put_user(__NR_rt_sigreturn,
 400                               (char *)(frame->retcode + 1)) ||
 401                    __put_user(0x00, (char *)(frame->retcode + 2)) ||
 402                    __put_user(0xf0, (char *)(frame->retcode + 3)) ||
 403                    __put_user(0xe0, (char *)(frame->retcode + 4)))
 404                        goto give_sigsegv;
 405
 406                flush_icache_range((u_long) frame->retcode,
 407                                   (u_long) frame->retcode + 5);
 408        }
 409
 410        /* Set up registers for signal handler */
 411        regs->sp = (unsigned long) frame;
 412        regs->pc = (unsigned long) ka->sa.sa_handler;
 413        regs->d0 = sig;
 414        regs->d1 = (long) &frame->info;
 415
 416        set_fs(USER_DS);
 417
 418        /* the tracer may want to single-step inside the handler */
 419        if (test_thread_flag(TIF_SINGLESTEP))
 420                ptrace_notify(SIGTRAP);
 421
 422#if DEBUG_SIG
 423        printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
 424               sig, current->comm, current->pid, frame, regs->pc,
 425               frame->pretcode);
 426#endif
 427
 428        return 0;
 429
 430give_sigsegv:
 431        force_sig(SIGSEGV, current);
 432        return -EFAULT;
 433}
 434
 435/*
 436 * handle the actual delivery of a signal to userspace
 437 */
 438static int handle_signal(int sig,
 439                         siginfo_t *info, struct k_sigaction *ka,
 440                         sigset_t *oldset, struct pt_regs *regs)
 441{
 442        int ret;
 443
 444        /* Are we from a system call? */
 445        if (regs->orig_d0 >= 0) {
 446                /* If so, check system call restarting.. */
 447                switch (regs->d0) {
 448                case -ERESTART_RESTARTBLOCK:
 449                case -ERESTARTNOHAND:
 450                        regs->d0 = -EINTR;
 451                        break;
 452
 453                case -ERESTARTSYS:
 454                        if (!(ka->sa.sa_flags & SA_RESTART)) {
 455                                regs->d0 = -EINTR;
 456                                break;
 457                        }
 458
 459                        /* fallthrough */
 460                case -ERESTARTNOINTR:
 461                        regs->d0 = regs->orig_d0;
 462                        regs->pc -= 2;
 463                }
 464        }
 465
 466        /* Set up the stack frame */
 467        if (ka->sa.sa_flags & SA_SIGINFO)
 468                ret = setup_rt_frame(sig, ka, info, oldset, regs);
 469        else
 470                ret = setup_frame(sig, ka, oldset, regs);
 471
 472        if (ret == 0) {
 473                spin_lock_irq(&current->sighand->siglock);
 474                sigorsets(&current->blocked, &current->blocked,
 475                          &ka->sa.sa_mask);
 476                if (!(ka->sa.sa_flags & SA_NODEFER))
 477                        sigaddset(&current->blocked, sig);
 478                recalc_sigpending();
 479                spin_unlock_irq(&current->sighand->siglock);
 480        }
 481
 482        return ret;
 483}
 484
 485/*
 486 * handle a potential signal
 487 */
 488static void do_signal(struct pt_regs *regs)
 489{
 490        struct k_sigaction ka;
 491        siginfo_t info;
 492        sigset_t *oldset;
 493        int signr;
 494
 495        /* we want the common case to go fast, which is why we may in certain
 496         * cases get here from kernel mode */
 497        if (!user_mode(regs))
 498                return;
 499
 500        if (test_thread_flag(TIF_RESTORE_SIGMASK))
 501                oldset = &current->saved_sigmask;
 502        else
 503                oldset = &current->blocked;
 504
 505        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 506        if (signr > 0) {
 507                if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
 508                        /* a signal was successfully delivered; the saved
 509                         * sigmask will have been stored in the signal frame,
 510                         * and will be restored by sigreturn, so we can simply
 511                         * clear the TIF_RESTORE_SIGMASK flag */
 512                        if (test_thread_flag(TIF_RESTORE_SIGMASK))
 513                                clear_thread_flag(TIF_RESTORE_SIGMASK);
 514                }
 515
 516                return;
 517        }
 518
 519        /* did we come from a system call? */
 520        if (regs->orig_d0 >= 0) {
 521                /* restart the system call - no handlers present */
 522                switch (regs->d0) {
 523                case -ERESTARTNOHAND:
 524                case -ERESTARTSYS:
 525                case -ERESTARTNOINTR:
 526                        regs->d0 = regs->orig_d0;
 527                        regs->pc -= 2;
 528                        break;
 529
 530                case -ERESTART_RESTARTBLOCK:
 531                        regs->d0 = __NR_restart_syscall;
 532                        regs->pc -= 2;
 533                        break;
 534                }
 535        }
 536
 537        /* if there's no signal to deliver, we just put the saved sigmask
 538         * back */
 539        if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
 540                clear_thread_flag(TIF_RESTORE_SIGMASK);
 541                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 542        }
 543}
 544
 545/*
 546 * notification of userspace execution resumption
 547 * - triggered by current->work.notify_resume
 548 */
 549asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
 550{
 551        /* Pending single-step? */
 552        if (thread_info_flags & _TIF_SINGLESTEP) {
 553#ifndef CONFIG_MN10300_USING_JTAG
 554                regs->epsw |= EPSW_T;
 555                clear_thread_flag(TIF_SINGLESTEP);
 556#else
 557                BUG(); /* no h/w single-step if using JTAG unit */
 558#endif
 559        }
 560
 561        /* deal with pending signal delivery */
 562        if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
 563                do_signal(regs);
 564}
 565