linux/arch/m68knommu/kernel/signal.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/m68knommu/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 * Linux/m68k support by Hamish Macdonald
  13 *
  14 * 68060 fixes by Jesper Skov
  15 *
  16 * 1997-12-01  Modified for POSIX.1b signals by Andreas Schwab
  17 *
  18 * mathemu support by Roman Zippel
  19 *  (Note: fpstate in the signal context is completely ignored for the emulator
  20 *         and the internal floating point format is put on stack)
  21 */
  22
  23/*
  24 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
  25 * Atari :-) Current limitation: Only one sigstack can be active at one time.
  26 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
  27 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
  28 * signal handlers!
  29 */
  30
  31#include <linux/sched.h>
  32#include <linux/mm.h>
  33#include <linux/kernel.h>
  34#include <linux/signal.h>
  35#include <linux/syscalls.h>
  36#include <linux/errno.h>
  37#include <linux/wait.h>
  38#include <linux/ptrace.h>
  39#include <linux/unistd.h>
  40#include <linux/stddef.h>
  41#include <linux/highuid.h>
  42#include <linux/tty.h>
  43#include <linux/personality.h>
  44#include <linux/binfmts.h>
  45
  46#include <asm/setup.h>
  47#include <asm/uaccess.h>
  48#include <asm/pgtable.h>
  49#include <asm/traps.h>
  50#include <asm/ucontext.h>
  51
  52#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
  53
  54void ret_from_user_signal(void);
  55void ret_from_user_rt_signal(void);
  56asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
  57
  58/*
  59 * Atomically swap in the new signal mask, and wait for a signal.
  60 */
  61asmlinkage int do_sigsuspend(struct pt_regs *regs)
  62{
  63        old_sigset_t mask = regs->d3;
  64        sigset_t saveset;
  65
  66        mask &= _BLOCKABLE;
  67        spin_lock_irq(&current->sighand->siglock);
  68        saveset = current->blocked;
  69        siginitset(&current->blocked, mask);
  70        recalc_sigpending();
  71        spin_unlock_irq(&current->sighand->siglock);
  72
  73        regs->d0 = -EINTR;
  74        while (1) {
  75                current->state = TASK_INTERRUPTIBLE;
  76                schedule();
  77                if (do_signal(&saveset, regs))
  78                        return -EINTR;
  79        }
  80}
  81
  82asmlinkage int
  83do_rt_sigsuspend(struct pt_regs *regs)
  84{
  85        sigset_t *unewset = (sigset_t *)regs->d1;
  86        size_t sigsetsize = (size_t)regs->d2;
  87        sigset_t saveset, newset;
  88
  89        /* XXX: Don't preclude handling different sized sigset_t's.  */
  90        if (sigsetsize != sizeof(sigset_t))
  91                return -EINVAL;
  92
  93        if (copy_from_user(&newset, unewset, sizeof(newset)))
  94                return -EFAULT;
  95        sigdelsetmask(&newset, ~_BLOCKABLE);
  96
  97        spin_lock_irq(&current->sighand->siglock);
  98        saveset = current->blocked;
  99        current->blocked = newset;
 100        recalc_sigpending();
 101        spin_unlock_irq(&current->sighand->siglock);
 102
 103        regs->d0 = -EINTR;
 104        while (1) {
 105                current->state = TASK_INTERRUPTIBLE;
 106                schedule();
 107                if (do_signal(&saveset, regs))
 108                        return -EINTR;
 109        }
 110}
 111
 112asmlinkage int 
 113sys_sigaction(int sig, const struct old_sigaction *act,
 114              struct old_sigaction *oact)
 115{
 116        struct k_sigaction new_ka, old_ka;
 117        int ret;
 118
 119        if (act) {
 120                old_sigset_t mask;
 121                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 122                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
 123                    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
 124                        return -EFAULT;
 125                __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 126                __get_user(mask, &act->sa_mask);
 127                siginitset(&new_ka.sa.sa_mask, mask);
 128        }
 129
 130        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 131
 132        if (!ret && oact) {
 133                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 134                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
 135                    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
 136                        return -EFAULT;
 137                __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 138                __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 139        }
 140
 141        return ret;
 142}
 143
 144asmlinkage int
 145sys_sigaltstack(const stack_t *uss, stack_t *uoss)
 146{
 147        return do_sigaltstack(uss, uoss, rdusp());
 148}
 149
 150
 151/*
 152 * Do a signal return; undo the signal stack.
 153 *
 154 * Keep the return code on the stack quadword aligned!
 155 * That makes the cache flush below easier.
 156 */
 157
 158struct sigframe
 159{
 160        char *pretcode;
 161        int sig;
 162        int code;
 163        struct sigcontext *psc;
 164        char retcode[8];
 165        unsigned long extramask[_NSIG_WORDS-1];
 166        struct sigcontext sc;
 167};
 168
 169struct rt_sigframe
 170{
 171        char *pretcode;
 172        int sig;
 173        struct siginfo *pinfo;
 174        void *puc;
 175        char retcode[8];
 176        struct siginfo info;
 177        struct ucontext uc;
 178};
 179
 180#ifdef CONFIG_FPU
 181
 182static unsigned char fpu_version = 0;   /* version number of fpu, set by setup_frame */
 183
 184static inline int restore_fpu_state(struct sigcontext *sc)
 185{
 186        int err = 1;
 187
 188        if (FPU_IS_EMU) {
 189            /* restore registers */
 190            memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
 191            memcpy(current->thread.fp, sc->sc_fpregs, 24);
 192            return 0;
 193        }
 194
 195        if (sc->sc_fpstate[0]) {
 196            /* Verify the frame format.  */
 197            if (sc->sc_fpstate[0] != fpu_version)
 198                goto out;
 199
 200            __asm__ volatile (".chip 68k/68881\n\t"
 201                              "fmovemx %0,%/fp0-%/fp1\n\t"
 202                              "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
 203                              ".chip 68k"
 204                              : /* no outputs */
 205                              : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
 206        }
 207        __asm__ volatile (".chip 68k/68881\n\t"
 208                          "frestore %0\n\t"
 209                          ".chip 68k" : : "m" (*sc->sc_fpstate));
 210        err = 0;
 211
 212out:
 213        return err;
 214}
 215
 216#define FPCONTEXT_SIZE  216
 217#define uc_fpstate      uc_filler[0]
 218#define uc_formatvec    uc_filler[FPCONTEXT_SIZE/4]
 219#define uc_extra        uc_filler[FPCONTEXT_SIZE/4+1]
 220
 221static inline int rt_restore_fpu_state(struct ucontext *uc)
 222{
 223        unsigned char fpstate[FPCONTEXT_SIZE];
 224        int context_size = 0;
 225        fpregset_t fpregs;
 226        int err = 1;
 227
 228        if (FPU_IS_EMU) {
 229                /* restore fpu control register */
 230                if (__copy_from_user(current->thread.fpcntl,
 231                                &uc->uc_mcontext.fpregs.f_pcr, 12))
 232                        goto out;
 233                /* restore all other fpu register */
 234                if (__copy_from_user(current->thread.fp,
 235                                uc->uc_mcontext.fpregs.f_fpregs, 96))
 236                        goto out;
 237                return 0;
 238        }
 239
 240        if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
 241                goto out;
 242        if (fpstate[0]) {
 243                context_size = fpstate[1];
 244
 245                /* Verify the frame format.  */
 246                if (fpstate[0] != fpu_version)
 247                        goto out;
 248                if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
 249                     sizeof(fpregs)))
 250                        goto out;
 251                __asm__ volatile (".chip 68k/68881\n\t"
 252                                  "fmovemx %0,%/fp0-%/fp7\n\t"
 253                                  "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
 254                                  ".chip 68k"
 255                                  : /* no outputs */
 256                                  : "m" (*fpregs.f_fpregs),
 257                                    "m" (fpregs.f_pcr));
 258        }
 259        if (context_size &&
 260            __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
 261                             context_size))
 262                goto out;
 263        __asm__ volatile (".chip 68k/68881\n\t"
 264                          "frestore %0\n\t"
 265                          ".chip 68k" : : "m" (*fpstate));
 266        err = 0;
 267
 268out:
 269        return err;
 270}
 271
 272#endif
 273
 274static inline int
 275restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
 276                   int *pd0)
 277{
 278        int formatvec;
 279        struct sigcontext context;
 280        int err = 0;
 281
 282        /* Always make any pending restarted system calls return -EINTR */
 283        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 284
 285        /* get previous context */
 286        if (copy_from_user(&context, usc, sizeof(context)))
 287                goto badframe;
 288        
 289        /* restore passed registers */
 290        regs->d1 = context.sc_d1;
 291        regs->a0 = context.sc_a0;
 292        regs->a1 = context.sc_a1;
 293        ((struct switch_stack *)regs - 1)->a5 = context.sc_a5;
 294        regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
 295        regs->pc = context.sc_pc;
 296        regs->orig_d0 = -1;             /* disable syscall checks */
 297        wrusp(context.sc_usp);
 298        formatvec = context.sc_formatvec;
 299        regs->format = formatvec >> 12;
 300        regs->vector = formatvec & 0xfff;
 301
 302#ifdef CONFIG_FPU
 303        err = restore_fpu_state(&context);
 304#endif
 305
 306        *pd0 = context.sc_d0;
 307        return err;
 308
 309badframe:
 310        return 1;
 311}
 312
 313static inline int
 314rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
 315                    struct ucontext *uc, int *pd0)
 316{
 317        int temp;
 318        greg_t *gregs = uc->uc_mcontext.gregs;
 319        unsigned long usp;
 320        int err;
 321
 322        /* Always make any pending restarted system calls return -EINTR */
 323        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 324
 325        err = __get_user(temp, &uc->uc_mcontext.version);
 326        if (temp != MCONTEXT_VERSION)
 327                goto badframe;
 328        /* restore passed registers */
 329        err |= __get_user(regs->d0, &gregs[0]);
 330        err |= __get_user(regs->d1, &gregs[1]);
 331        err |= __get_user(regs->d2, &gregs[2]);
 332        err |= __get_user(regs->d3, &gregs[3]);
 333        err |= __get_user(regs->d4, &gregs[4]);
 334        err |= __get_user(regs->d5, &gregs[5]);
 335        err |= __get_user(sw->d6, &gregs[6]);
 336        err |= __get_user(sw->d7, &gregs[7]);
 337        err |= __get_user(regs->a0, &gregs[8]);
 338        err |= __get_user(regs->a1, &gregs[9]);
 339        err |= __get_user(regs->a2, &gregs[10]);
 340        err |= __get_user(sw->a3, &gregs[11]);
 341        err |= __get_user(sw->a4, &gregs[12]);
 342        err |= __get_user(sw->a5, &gregs[13]);
 343        err |= __get_user(sw->a6, &gregs[14]);
 344        err |= __get_user(usp, &gregs[15]);
 345        wrusp(usp);
 346        err |= __get_user(regs->pc, &gregs[16]);
 347        err |= __get_user(temp, &gregs[17]);
 348        regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
 349        regs->orig_d0 = -1;             /* disable syscall checks */
 350        regs->format = temp >> 12;
 351        regs->vector = temp & 0xfff;
 352
 353        if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
 354                goto badframe;
 355
 356        *pd0 = regs->d0;
 357        return err;
 358
 359badframe:
 360        return 1;
 361}
 362
 363asmlinkage int do_sigreturn(unsigned long __unused)
 364{
 365        struct switch_stack *sw = (struct switch_stack *) &__unused;
 366        struct pt_regs *regs = (struct pt_regs *) (sw + 1);
 367        unsigned long usp = rdusp();
 368        struct sigframe *frame = (struct sigframe *)(usp - 4);
 369        sigset_t set;
 370        int d0;
 371
 372        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 373                goto badframe;
 374        if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
 375            (_NSIG_WORDS > 1 &&
 376             __copy_from_user(&set.sig[1], &frame->extramask,
 377                              sizeof(frame->extramask))))
 378                goto badframe;
 379
 380        sigdelsetmask(&set, ~_BLOCKABLE);
 381        spin_lock_irq(&current->sighand->siglock);
 382        current->blocked = set;
 383        recalc_sigpending();
 384        spin_unlock_irq(&current->sighand->siglock);
 385        
 386        if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
 387                goto badframe;
 388        return d0;
 389
 390badframe:
 391        force_sig(SIGSEGV, current);
 392        return 0;
 393}
 394
 395asmlinkage int do_rt_sigreturn(unsigned long __unused)
 396{
 397        struct switch_stack *sw = (struct switch_stack *) &__unused;
 398        struct pt_regs *regs = (struct pt_regs *) (sw + 1);
 399        unsigned long usp = rdusp();
 400        struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
 401        sigset_t set;
 402        int d0;
 403
 404        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 405                goto badframe;
 406        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 407                goto badframe;
 408
 409        sigdelsetmask(&set, ~_BLOCKABLE);
 410        spin_lock_irq(&current->sighand->siglock);
 411        current->blocked = set;
 412        recalc_sigpending();
 413        spin_unlock_irq(&current->sighand->siglock);
 414        
 415        if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
 416                goto badframe;
 417        return d0;
 418
 419badframe:
 420        force_sig(SIGSEGV, current);
 421        return 0;
 422}
 423
 424#ifdef CONFIG_FPU
 425/*
 426 * Set up a signal frame.
 427 */
 428
 429static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
 430{
 431        if (FPU_IS_EMU) {
 432                /* save registers */
 433                memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
 434                memcpy(sc->sc_fpregs, current->thread.fp, 24);
 435                return;
 436        }
 437
 438        __asm__ volatile (".chip 68k/68881\n\t"
 439                          "fsave %0\n\t"
 440                          ".chip 68k"
 441                          : : "m" (*sc->sc_fpstate) : "memory");
 442
 443        if (sc->sc_fpstate[0]) {
 444                fpu_version = sc->sc_fpstate[0];
 445                __asm__ volatile (".chip 68k/68881\n\t"
 446                                  "fmovemx %/fp0-%/fp1,%0\n\t"
 447                                  "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
 448                                  ".chip 68k"
 449                                  : /* no outputs */
 450                                  : "m" (*sc->sc_fpregs),
 451                                    "m" (*sc->sc_fpcntl)
 452                                  : "memory");
 453        }
 454}
 455
 456static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
 457{
 458        unsigned char fpstate[FPCONTEXT_SIZE];
 459        int context_size = 0;
 460        int err = 0;
 461
 462        if (FPU_IS_EMU) {
 463                /* save fpu control register */
 464                err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr,
 465                                current->thread.fpcntl, 12);
 466                /* save all other fpu register */
 467                err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
 468                                current->thread.fp, 96);
 469                return err;
 470        }
 471
 472        __asm__ volatile (".chip 68k/68881\n\t"
 473                          "fsave %0\n\t"
 474                          ".chip 68k"
 475                          : : "m" (*fpstate) : "memory");
 476
 477        err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
 478        if (fpstate[0]) {
 479                fpregset_t fpregs;
 480                context_size = fpstate[1];
 481                fpu_version = fpstate[0];
 482                __asm__ volatile (".chip 68k/68881\n\t"
 483                                  "fmovemx %/fp0-%/fp7,%0\n\t"
 484                                  "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
 485                                  ".chip 68k"
 486                                  : /* no outputs */
 487                                  : "m" (*fpregs.f_fpregs),
 488                                    "m" (fpregs.f_pcr)
 489                                  : "memory");
 490                err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
 491                                    sizeof(fpregs));
 492        }
 493        if (context_size)
 494                err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
 495                                    context_size);
 496        return err;
 497}
 498
 499#endif
 500
 501static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
 502                             unsigned long mask)
 503{
 504        sc->sc_mask = mask;
 505        sc->sc_usp = rdusp();
 506        sc->sc_d0 = regs->d0;
 507        sc->sc_d1 = regs->d1;
 508        sc->sc_a0 = regs->a0;
 509        sc->sc_a1 = regs->a1;
 510        sc->sc_a5 = ((struct switch_stack *)regs - 1)->a5;
 511        sc->sc_sr = regs->sr;
 512        sc->sc_pc = regs->pc;
 513        sc->sc_formatvec = regs->format << 12 | regs->vector;
 514#ifdef CONFIG_FPU
 515        save_fpu_state(sc, regs);
 516#endif
 517}
 518
 519static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
 520{
 521        struct switch_stack *sw = (struct switch_stack *)regs - 1;
 522        greg_t *gregs = uc->uc_mcontext.gregs;
 523        int err = 0;
 524
 525        err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
 526        err |= __put_user(regs->d0, &gregs[0]);
 527        err |= __put_user(regs->d1, &gregs[1]);
 528        err |= __put_user(regs->d2, &gregs[2]);
 529        err |= __put_user(regs->d3, &gregs[3]);
 530        err |= __put_user(regs->d4, &gregs[4]);
 531        err |= __put_user(regs->d5, &gregs[5]);
 532        err |= __put_user(sw->d6, &gregs[6]);
 533        err |= __put_user(sw->d7, &gregs[7]);
 534        err |= __put_user(regs->a0, &gregs[8]);
 535        err |= __put_user(regs->a1, &gregs[9]);
 536        err |= __put_user(regs->a2, &gregs[10]);
 537        err |= __put_user(sw->a3, &gregs[11]);
 538        err |= __put_user(sw->a4, &gregs[12]);
 539        err |= __put_user(sw->a5, &gregs[13]);
 540        err |= __put_user(sw->a6, &gregs[14]);
 541        err |= __put_user(rdusp(), &gregs[15]);
 542        err |= __put_user(regs->pc, &gregs[16]);
 543        err |= __put_user(regs->sr, &gregs[17]);
 544#ifdef CONFIG_FPU
 545        err |= rt_save_fpu_state(uc, regs);
 546#endif
 547        return err;
 548}
 549
 550static inline void *
 551get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 552{
 553        unsigned long usp;
 554
 555        /* Default to using normal stack.  */
 556        usp = rdusp();
 557
 558        /* This is the X/Open sanctioned signal stack switching.  */
 559        if (ka->sa.sa_flags & SA_ONSTACK) {
 560                if (!sas_ss_flags(usp))
 561                        usp = current->sas_ss_sp + current->sas_ss_size;
 562        }
 563        return (void *)((usp - frame_size) & -8UL);
 564}
 565
 566static void setup_frame (int sig, struct k_sigaction *ka,
 567                         sigset_t *set, struct pt_regs *regs)
 568{
 569        struct sigframe *frame;
 570        struct sigcontext context;
 571        int err = 0;
 572
 573        frame = get_sigframe(ka, regs, sizeof(*frame));
 574
 575        err |= __put_user((current_thread_info()->exec_domain
 576                           && current_thread_info()->exec_domain->signal_invmap
 577                           && sig < 32
 578                           ? current_thread_info()->exec_domain->signal_invmap[sig]
 579                           : sig),
 580                          &frame->sig);
 581
 582        err |= __put_user(regs->vector, &frame->code);
 583        err |= __put_user(&frame->sc, &frame->psc);
 584
 585        if (_NSIG_WORDS > 1)
 586                err |= copy_to_user(frame->extramask, &set->sig[1],
 587                                    sizeof(frame->extramask));
 588
 589        setup_sigcontext(&context, regs, set->sig[0]);
 590        err |= copy_to_user (&frame->sc, &context, sizeof(context));
 591
 592        /* Set up to return from userspace.  */
 593        err |= __put_user((void *) ret_from_user_signal, &frame->pretcode);
 594
 595        if (err)
 596                goto give_sigsegv;
 597
 598        /* Set up registers for signal handler */
 599        wrusp ((unsigned long) frame);
 600        regs->pc = (unsigned long) ka->sa.sa_handler;
 601        ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
 602        regs->format = 0x4; /*set format byte to make stack appear modulo 4 
 603                                                which it will be when doing the rte */
 604
 605adjust_stack:
 606        /* Prepare to skip over the extra stuff in the exception frame.  */
 607        if (regs->stkadj) {
 608                struct pt_regs *tregs =
 609                        (struct pt_regs *)((ulong)regs + regs->stkadj);
 610#if defined(DEBUG)
 611                printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
 612#endif
 613                /* This must be copied with decreasing addresses to
 614                   handle overlaps.  */
 615                tregs->vector = 0;
 616                tregs->format = 0;
 617                tregs->pc = regs->pc;
 618                tregs->sr = regs->sr;
 619        }
 620        return;
 621
 622give_sigsegv:
 623        force_sigsegv(sig, current);
 624        goto adjust_stack;
 625}
 626
 627static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
 628                            sigset_t *set, struct pt_regs *regs)
 629{
 630        struct rt_sigframe *frame;
 631        int err = 0;
 632
 633        frame = get_sigframe(ka, regs, sizeof(*frame));
 634
 635        err |= __put_user((current_thread_info()->exec_domain
 636                           && current_thread_info()->exec_domain->signal_invmap
 637                           && sig < 32
 638                           ? current_thread_info()->exec_domain->signal_invmap[sig]
 639                           : sig),
 640                          &frame->sig);
 641        err |= __put_user(&frame->info, &frame->pinfo);
 642        err |= __put_user(&frame->uc, &frame->puc);
 643        err |= copy_siginfo_to_user(&frame->info, info);
 644
 645        /* Create the ucontext.  */
 646        err |= __put_user(0, &frame->uc.uc_flags);
 647        err |= __put_user(0, &frame->uc.uc_link);
 648        err |= __put_user((void *)current->sas_ss_sp,
 649                          &frame->uc.uc_stack.ss_sp);
 650        err |= __put_user(sas_ss_flags(rdusp()),
 651                          &frame->uc.uc_stack.ss_flags);
 652        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
 653        err |= rt_setup_ucontext(&frame->uc, regs);
 654        err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
 655
 656        /* Set up to return from userspace.  */
 657        err |= __put_user((void *) ret_from_user_rt_signal, &frame->pretcode);
 658
 659        if (err)
 660                goto give_sigsegv;
 661
 662        /* Set up registers for signal handler */
 663        wrusp ((unsigned long) frame);
 664        regs->pc = (unsigned long) ka->sa.sa_handler;
 665        ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
 666        regs->format = 0x4; /*set format byte to make stack appear modulo 4 
 667                                                which it will be when doing the rte */
 668
 669adjust_stack:
 670        /* Prepare to skip over the extra stuff in the exception frame.  */
 671        if (regs->stkadj) {
 672                struct pt_regs *tregs =
 673                        (struct pt_regs *)((ulong)regs + regs->stkadj);
 674#if defined(DEBUG)
 675                printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
 676#endif
 677                /* This must be copied with decreasing addresses to
 678                   handle overlaps.  */
 679                tregs->vector = 0;
 680                tregs->format = 0;
 681                tregs->pc = regs->pc;
 682                tregs->sr = regs->sr;
 683        }
 684        return;
 685
 686give_sigsegv:
 687        force_sigsegv(sig, current);
 688        goto adjust_stack;
 689}
 690
 691static inline void
 692handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
 693{
 694        switch (regs->d0) {
 695        case -ERESTARTNOHAND:
 696                if (!has_handler)
 697                        goto do_restart;
 698                regs->d0 = -EINTR;
 699                break;
 700
 701        case -ERESTART_RESTARTBLOCK:
 702                if (!has_handler) {
 703                        regs->d0 = __NR_restart_syscall;
 704                        regs->pc -= 2;
 705                        break;
 706                }
 707                regs->d0 = -EINTR;
 708                break;
 709
 710        case -ERESTARTSYS:
 711                if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
 712                        regs->d0 = -EINTR;
 713                        break;
 714                }
 715        /* fallthrough */
 716        case -ERESTARTNOINTR:
 717        do_restart:
 718                regs->d0 = regs->orig_d0;
 719                regs->pc -= 2;
 720                break;
 721        }
 722}
 723
 724/*
 725 * OK, we're invoking a handler
 726 */
 727static void
 728handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
 729              sigset_t *oldset, struct pt_regs *regs)
 730{
 731        /* are we from a system call? */
 732        if (regs->orig_d0 >= 0)
 733                /* If so, check system call restarting.. */
 734                handle_restart(regs, ka, 1);
 735
 736        /* set up the stack frame */
 737        if (ka->sa.sa_flags & SA_SIGINFO)
 738                setup_rt_frame(sig, ka, info, oldset, regs);
 739        else
 740                setup_frame(sig, ka, oldset, regs);
 741
 742        if (ka->sa.sa_flags & SA_ONESHOT)
 743                ka->sa.sa_handler = SIG_DFL;
 744
 745        spin_lock_irq(&current->sighand->siglock);
 746        sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 747        if (!(ka->sa.sa_flags & SA_NODEFER))
 748                sigaddset(&current->blocked,sig);
 749        recalc_sigpending();
 750        spin_unlock_irq(&current->sighand->siglock);
 751}
 752
 753/*
 754 * Note that 'init' is a special process: it doesn't get signals it doesn't
 755 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 756 * mistake.
 757 */
 758asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
 759{
 760        struct k_sigaction ka;
 761        siginfo_t info;
 762        int signr;
 763
 764        /*
 765         * We want the common case to go fast, which
 766         * is why we may in certain cases get here from
 767         * kernel mode. Just return without doing anything
 768         * if so.
 769         */
 770        if (!user_mode(regs))
 771                return 1;
 772
 773        if (!oldset)
 774                oldset = &current->blocked;
 775
 776        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 777        if (signr > 0) {
 778                /* Whee!  Actually deliver the signal.  */
 779                handle_signal(signr, &ka, &info, oldset, regs);
 780                return 1;
 781        }
 782
 783        /* Did we come from a system call? */
 784        if (regs->orig_d0 >= 0) {
 785                /* Restart the system call - no handlers present */
 786                handle_restart(regs, NULL, 0);
 787        }
 788        return 0;
 789}
 790