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