linux/arch/h8300/kernel/signal.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/h8300/kernel/signal.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License.  See the file COPYING in the main directory of this archive
   8 * for more details.
   9 */
  10
  11/*
  12 * uClinux H8/300 support by Yoshinori Sato <ysato@users.sourceforge.jp>
  13 *                and David McCullough <davidm@snapgear.com>
  14 *
  15 * Based on
  16 * Linux/m68k by Hamish Macdonald
  17 */
  18
  19/*
  20 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
  21 * Atari :-) Current limitation: Only one sigstack can be active at one time.
  22 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
  23 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
  24 * signal handlers!
  25 */
  26
  27#include <linux/sched.h>
  28#include <linux/mm.h>
  29#include <linux/kernel.h>
  30#include <linux/signal.h>
  31#include <linux/syscalls.h>
  32#include <linux/errno.h>
  33#include <linux/wait.h>
  34#include <linux/ptrace.h>
  35#include <linux/unistd.h>
  36#include <linux/stddef.h>
  37#include <linux/highuid.h>
  38#include <linux/personality.h>
  39#include <linux/tty.h>
  40#include <linux/binfmts.h>
  41#include <linux/freezer.h>
  42#include <linux/tracehook.h>
  43
  44#include <asm/setup.h>
  45#include <asm/uaccess.h>
  46#include <asm/pgtable.h>
  47#include <asm/traps.h>
  48#include <asm/ucontext.h>
  49
  50#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
  51
  52asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
  53
  54/*
  55 * Atomically swap in the new signal mask, and wait for a signal.
  56 */
  57asmlinkage int do_sigsuspend(struct pt_regs *regs)
  58{
  59        old_sigset_t mask = regs->er3;
  60        sigset_t saveset;
  61
  62        mask &= _BLOCKABLE;
  63        spin_lock_irq(&current->sighand->siglock);
  64        saveset = current->blocked;
  65        siginitset(&current->blocked, mask);
  66        recalc_sigpending();
  67        spin_unlock_irq(&current->sighand->siglock);
  68
  69        regs->er0 = -EINTR;
  70        while (1) {
  71                current->state = TASK_INTERRUPTIBLE;
  72                schedule();
  73                if (do_signal(regs, &saveset))
  74                        return -EINTR;
  75        }
  76}
  77
  78asmlinkage int
  79do_rt_sigsuspend(struct pt_regs *regs)
  80{
  81        sigset_t *unewset = (sigset_t *)regs->er1;
  82        size_t sigsetsize = (size_t)regs->er2;
  83        sigset_t saveset, newset;
  84
  85        /* XXX: Don't preclude handling different sized sigset_t's.  */
  86        if (sigsetsize != sizeof(sigset_t))
  87                return -EINVAL;
  88
  89        if (copy_from_user(&newset, unewset, sizeof(newset)))
  90                return -EFAULT;
  91        sigdelsetmask(&newset, ~_BLOCKABLE);
  92
  93        spin_lock_irq(&current->sighand->siglock);
  94        saveset = current->blocked;
  95        current->blocked = newset;
  96        recalc_sigpending();
  97        spin_unlock_irq(&current->sighand->siglock);
  98
  99        regs->er0 = -EINTR;
 100        while (1) {
 101                current->state = TASK_INTERRUPTIBLE;
 102                schedule();
 103                if (do_signal(regs, &saveset))
 104                        return -EINTR;
 105        }
 106}
 107
 108asmlinkage int 
 109sys_sigaction(int sig, const struct old_sigaction *act,
 110              struct old_sigaction *oact)
 111{
 112        struct k_sigaction new_ka, old_ka;
 113        int ret;
 114
 115        if (act) {
 116                old_sigset_t mask;
 117                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 118                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
 119                    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
 120                        return -EFAULT;
 121                __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 122                __get_user(mask, &act->sa_mask);
 123                siginitset(&new_ka.sa.sa_mask, mask);
 124        }
 125
 126        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 127
 128        if (!ret && oact) {
 129                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 130                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
 131                    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
 132                        return -EFAULT;
 133                __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 134                __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 135        }
 136
 137        return ret;
 138}
 139
 140asmlinkage int
 141sys_sigaltstack(const stack_t *uss, stack_t *uoss)
 142{
 143        return do_sigaltstack(uss, uoss, rdusp());
 144}
 145
 146
 147/*
 148 * Do a signal return; undo the signal stack.
 149 *
 150 * Keep the return code on the stack quadword aligned!
 151 * That makes the cache flush below easier.
 152 */
 153
 154struct sigframe
 155{
 156        long dummy_er0;
 157        long dummy_vector;
 158#if defined(CONFIG_CPU_H8S)
 159        short dummy_exr;
 160#endif
 161        long dummy_pc;
 162        char *pretcode;
 163        unsigned char retcode[8];
 164        unsigned long extramask[_NSIG_WORDS-1];
 165        struct sigcontext sc;
 166        int sig;
 167} __attribute__((aligned(2),packed));
 168
 169struct rt_sigframe
 170{
 171        long dummy_er0;
 172        long dummy_vector;
 173#if defined(CONFIG_CPU_H8S)
 174        short dummy_exr;
 175#endif
 176        long dummy_pc;
 177        char *pretcode;
 178        struct siginfo *pinfo;
 179        void *puc;
 180        unsigned char retcode[8];
 181        struct siginfo info;
 182        struct ucontext uc;
 183        int sig;
 184} __attribute__((aligned(2),packed));
 185
 186static inline int
 187restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc,
 188                   int *pd0)
 189{
 190        int err = 0;
 191        unsigned int ccr;
 192        unsigned int usp;
 193        unsigned int er0;
 194
 195        /* Always make any pending restarted system calls return -EINTR */
 196        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 197
 198#define COPY(r) err |= __get_user(regs->r, &usc->sc_##r)    /* restore passed registers */
 199        COPY(er1);
 200        COPY(er2);
 201        COPY(er3);
 202        COPY(er5);
 203        COPY(pc);
 204        ccr = regs->ccr & 0x10;
 205        COPY(ccr);
 206#undef COPY
 207        regs->ccr &= 0xef;
 208        regs->ccr |= ccr;
 209        regs->orig_er0 = -1;            /* disable syscall checks */
 210        err |= __get_user(usp, &usc->sc_usp);
 211        wrusp(usp);
 212
 213        err |= __get_user(er0, &usc->sc_er0);
 214        *pd0 = er0;
 215        return err;
 216}
 217
 218asmlinkage int do_sigreturn(unsigned long __unused,...)
 219{
 220        struct pt_regs *regs = (struct pt_regs *) (&__unused - 1);
 221        unsigned long usp = rdusp();
 222        struct sigframe *frame = (struct sigframe *)(usp - 4);
 223        sigset_t set;
 224        int er0;
 225
 226        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 227                goto badframe;
 228        if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
 229            (_NSIG_WORDS > 1 &&
 230             __copy_from_user(&set.sig[1], &frame->extramask,
 231                              sizeof(frame->extramask))))
 232                goto badframe;
 233
 234        sigdelsetmask(&set, ~_BLOCKABLE);
 235        spin_lock_irq(&current->sighand->siglock);
 236        current->blocked = set;
 237        recalc_sigpending();
 238        spin_unlock_irq(&current->sighand->siglock);
 239        
 240        if (restore_sigcontext(regs, &frame->sc, &er0))
 241                goto badframe;
 242        return er0;
 243
 244badframe:
 245        force_sig(SIGSEGV, current);
 246        return 0;
 247}
 248
 249asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
 250{
 251        struct pt_regs *regs = (struct pt_regs *) &__unused;
 252        unsigned long usp = rdusp();
 253        struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
 254        sigset_t set;
 255        int er0;
 256
 257        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 258                goto badframe;
 259        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 260                goto badframe;
 261
 262        sigdelsetmask(&set, ~_BLOCKABLE);
 263        spin_unlock_irq(&current->sighand->siglock);
 264        current->blocked = set;
 265        recalc_sigpending();
 266        spin_lock_irq(&current->sighand->siglock);
 267        
 268        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
 269                goto badframe;
 270
 271        if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
 272                goto badframe;
 273
 274        return er0;
 275
 276badframe:
 277        force_sig(SIGSEGV, current);
 278        return 0;
 279}
 280
 281static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 282                             unsigned long mask)
 283{
 284        int err = 0;
 285
 286        err |= __put_user(regs->er0, &sc->sc_er0);
 287        err |= __put_user(regs->er1, &sc->sc_er1);
 288        err |= __put_user(regs->er2, &sc->sc_er2);
 289        err |= __put_user(regs->er3, &sc->sc_er3);
 290        err |= __put_user(regs->er4, &sc->sc_er4);
 291        err |= __put_user(regs->er5, &sc->sc_er5);
 292        err |= __put_user(regs->er6, &sc->sc_er6);
 293        err |= __put_user(rdusp(),   &sc->sc_usp);
 294        err |= __put_user(regs->pc,  &sc->sc_pc);
 295        err |= __put_user(regs->ccr, &sc->sc_ccr);
 296        err |= __put_user(mask,      &sc->sc_mask);
 297
 298        return err;
 299}
 300
 301static inline void *
 302get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 303{
 304        unsigned long usp;
 305
 306        /* Default to using normal stack.  */
 307        usp = rdusp();
 308
 309        /* This is the X/Open sanctioned signal stack switching.  */
 310        if (ka->sa.sa_flags & SA_ONSTACK) {
 311                if (!sas_ss_flags(usp))
 312                        usp = current->sas_ss_sp + current->sas_ss_size;
 313        }
 314        return (void *)((usp - frame_size) & -8UL);
 315}
 316
 317static void setup_frame (int sig, struct k_sigaction *ka,
 318                         sigset_t *set, struct pt_regs *regs)
 319{
 320        struct sigframe *frame;
 321        int err = 0;
 322        int usig;
 323        unsigned char *ret;
 324
 325        frame = get_sigframe(ka, regs, sizeof(*frame));
 326
 327        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 328                goto give_sigsegv;
 329
 330        usig = current_thread_info()->exec_domain
 331                && current_thread_info()->exec_domain->signal_invmap
 332                && sig < 32
 333                ? current_thread_info()->exec_domain->signal_invmap[sig]
 334                : sig;
 335
 336        err |= __put_user(usig, &frame->sig);
 337        if (err)
 338                goto give_sigsegv;
 339
 340        err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
 341        if (err)
 342                goto give_sigsegv;
 343
 344        if (_NSIG_WORDS > 1) {
 345                err |= copy_to_user(frame->extramask, &set->sig[1],
 346                                    sizeof(frame->extramask));
 347                if (err)
 348                        goto give_sigsegv;
 349        }
 350
 351        ret = frame->retcode;
 352        if (ka->sa.sa_flags & SA_RESTORER)
 353                ret = (unsigned char *)(ka->sa.sa_restorer);
 354        else {
 355                /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */
 356                err |= __put_user(0x1a80f800 + (__NR_sigreturn & 0xff),
 357                                  (unsigned long *)(frame->retcode + 0));
 358                err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4));
 359        }
 360
 361        /* Set up to return from userspace.  */
 362        err |= __put_user(ret, &frame->pretcode);
 363
 364        if (err)
 365                goto give_sigsegv;
 366
 367        /* Set up registers for signal handler */
 368        wrusp ((unsigned long) frame);
 369        regs->pc = (unsigned long) ka->sa.sa_handler;
 370        regs->er0 = (current_thread_info()->exec_domain
 371                           && current_thread_info()->exec_domain->signal_invmap
 372                           && sig < 32
 373                           ? current_thread_info()->exec_domain->signal_invmap[sig]
 374                          : sig);
 375        regs->er1 = (unsigned long)&(frame->sc);
 376        regs->er5 = current->mm->start_data;    /* GOT base */
 377
 378        return;
 379
 380give_sigsegv:
 381        force_sigsegv(sig, current);
 382}
 383
 384static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
 385                            sigset_t *set, struct pt_regs *regs)
 386{
 387        struct rt_sigframe *frame;
 388        int err = 0;
 389        int usig;
 390        unsigned char *ret;
 391
 392        frame = get_sigframe(ka, regs, sizeof(*frame));
 393
 394        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 395                goto give_sigsegv;
 396
 397        usig = current_thread_info()->exec_domain
 398                && current_thread_info()->exec_domain->signal_invmap
 399                && sig < 32
 400                ? current_thread_info()->exec_domain->signal_invmap[sig]
 401                : sig;
 402
 403        err |= __put_user(usig, &frame->sig);
 404        if (err)
 405                goto give_sigsegv;
 406
 407        err |= __put_user(&frame->info, &frame->pinfo);
 408        err |= __put_user(&frame->uc, &frame->puc);
 409        err |= copy_siginfo_to_user(&frame->info, info);
 410        if (err)
 411                goto give_sigsegv;
 412
 413        /* Create the ucontext.  */
 414        err |= __put_user(0, &frame->uc.uc_flags);
 415        err |= __put_user(0, &frame->uc.uc_link);
 416        err |= __put_user((void *)current->sas_ss_sp,
 417                          &frame->uc.uc_stack.ss_sp);
 418        err |= __put_user(sas_ss_flags(rdusp()),
 419                          &frame->uc.uc_stack.ss_flags);
 420        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
 421        err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
 422        err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
 423        if (err)
 424                goto give_sigsegv;
 425
 426        /* Set up to return from userspace.  */
 427        ret = frame->retcode;
 428        if (ka->sa.sa_flags & SA_RESTORER)
 429                ret = (unsigned char *)(ka->sa.sa_restorer);
 430        else {
 431                /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */
 432                err |= __put_user(0x1a80f800 + (__NR_sigreturn & 0xff),
 433                                  (unsigned long *)(frame->retcode + 0));
 434                err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4));
 435        }
 436        err |= __put_user(ret, &frame->pretcode);
 437
 438        if (err)
 439                goto give_sigsegv;
 440
 441        /* Set up registers for signal handler */
 442        wrusp ((unsigned long) frame);
 443        regs->pc  = (unsigned long) ka->sa.sa_handler;
 444        regs->er0 = (current_thread_info()->exec_domain
 445                     && current_thread_info()->exec_domain->signal_invmap
 446                     && sig < 32
 447                     ? current_thread_info()->exec_domain->signal_invmap[sig]
 448                     : sig);
 449        regs->er1 = (unsigned long)&(frame->info);
 450        regs->er2 = (unsigned long)&frame->uc;
 451        regs->er5 = current->mm->start_data;    /* GOT base */
 452
 453        return;
 454
 455give_sigsegv:
 456        force_sigsegv(sig, current);
 457}
 458
 459/*
 460 * OK, we're invoking a handler
 461 */
 462static void
 463handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 464              sigset_t *oldset, struct pt_regs * regs)
 465{
 466        /* are we from a system call? */
 467        if (regs->orig_er0 >= 0) {
 468                switch (regs->er0) {
 469                        case -ERESTART_RESTARTBLOCK:
 470                        case -ERESTARTNOHAND:
 471                                regs->er0 = -EINTR;
 472                                break;
 473
 474                        case -ERESTARTSYS:
 475                                if (!(ka->sa.sa_flags & SA_RESTART)) {
 476                                        regs->er0 = -EINTR;
 477                                        break;
 478                                }
 479                        /* fallthrough */
 480                        case -ERESTARTNOINTR:
 481                                regs->er0 = regs->orig_er0;
 482                                regs->pc -= 2;
 483                }
 484        }
 485
 486        /* set up the stack frame */
 487        if (ka->sa.sa_flags & SA_SIGINFO)
 488                setup_rt_frame(sig, ka, info, oldset, regs);
 489        else
 490                setup_frame(sig, ka, oldset, regs);
 491
 492        spin_lock_irq(&current->sighand->siglock);
 493        sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 494        if (!(ka->sa.sa_flags & SA_NODEFER))
 495                sigaddset(&current->blocked,sig);
 496        recalc_sigpending();
 497        spin_unlock_irq(&current->sighand->siglock);
 498}
 499
 500/*
 501 * Note that 'init' is a special process: it doesn't get signals it doesn't
 502 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 503 * mistake.
 504 */
 505asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
 506{
 507        siginfo_t info;
 508        int signr;
 509        struct k_sigaction ka;
 510
 511        /*
 512         * We want the common case to go fast, which
 513         * is why we may in certain cases get here from
 514         * kernel mode. Just return without doing anything
 515         * if so.
 516         */
 517        if ((regs->ccr & 0x10))
 518                return 1;
 519
 520        if (try_to_freeze())
 521                goto no_signal;
 522
 523        current->thread.esp0 = (unsigned long) regs;
 524
 525        if (!oldset)
 526                oldset = &current->blocked;
 527
 528        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 529        if (signr > 0) {
 530                /* Whee!  Actually deliver the signal.  */
 531                handle_signal(signr, &info, &ka, oldset, regs);
 532                return 1;
 533        }
 534 no_signal:
 535        /* Did we come from a system call? */
 536        if (regs->orig_er0 >= 0) {
 537                /* Restart the system call - no handlers present */
 538                if (regs->er0 == -ERESTARTNOHAND ||
 539                    regs->er0 == -ERESTARTSYS ||
 540                    regs->er0 == -ERESTARTNOINTR) {
 541                        regs->er0 = regs->orig_er0;
 542                        regs->pc -= 2;
 543                }
 544                if (regs->er0 == -ERESTART_RESTARTBLOCK){
 545                        regs->er0 = __NR_restart_syscall;
 546                        regs->pc -= 2;
 547                }
 548        }
 549        return 0;
 550}
 551
 552asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
 553{
 554        if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
 555                do_signal(regs, NULL);
 556
 557        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 558                clear_thread_flag(TIF_NOTIFY_RESUME);
 559                tracehook_notify_resume(regs);
 560                if (current->replacement_session_keyring)
 561                        key_replace_session_keyring();
 562        }
 563}
 564