linux/arch/m68k/kernel/signal.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/m68k/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/personality.h>
  43#include <linux/tty.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
  54const int frame_extra_sizes[16] = {
  55  [1]   = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
  56  [2]   = sizeof(((struct frame *)0)->un.fmt2),
  57  [3]   = sizeof(((struct frame *)0)->un.fmt3),
  58  [4]   = sizeof(((struct frame *)0)->un.fmt4),
  59  [5]   = -1, /* sizeof(((struct frame *)0)->un.fmt5), */
  60  [6]   = -1, /* sizeof(((struct frame *)0)->un.fmt6), */
  61  [7]   = sizeof(((struct frame *)0)->un.fmt7),
  62  [8]   = -1, /* sizeof(((struct frame *)0)->un.fmt8), */
  63  [9]   = sizeof(((struct frame *)0)->un.fmt9),
  64  [10]  = sizeof(((struct frame *)0)->un.fmta),
  65  [11]  = sizeof(((struct frame *)0)->un.fmtb),
  66  [12]  = -1, /* sizeof(((struct frame *)0)->un.fmtc), */
  67  [13]  = -1, /* sizeof(((struct frame *)0)->un.fmtd), */
  68  [14]  = -1, /* sizeof(((struct frame *)0)->un.fmte), */
  69  [15]  = -1, /* sizeof(((struct frame *)0)->un.fmtf), */
  70};
  71
  72/*
  73 * Atomically swap in the new signal mask, and wait for a signal.
  74 */
  75asmlinkage int
  76sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
  77{
  78        mask &= _BLOCKABLE;
  79        spin_lock_irq(&current->sighand->siglock);
  80        current->saved_sigmask = current->blocked;
  81        siginitset(&current->blocked, mask);
  82        recalc_sigpending();
  83        spin_unlock_irq(&current->sighand->siglock);
  84
  85        current->state = TASK_INTERRUPTIBLE;
  86        schedule();
  87        set_restore_sigmask();
  88
  89        return -ERESTARTNOHAND;
  90}
  91
  92asmlinkage int
  93sys_sigaction(int sig, const struct old_sigaction __user *act,
  94              struct old_sigaction __user *oact)
  95{
  96        struct k_sigaction new_ka, old_ka;
  97        int ret;
  98
  99        if (act) {
 100                old_sigset_t mask;
 101                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 102                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
 103                    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
 104                    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
 105                    __get_user(mask, &act->sa_mask))
 106                        return -EFAULT;
 107                siginitset(&new_ka.sa.sa_mask, mask);
 108        }
 109
 110        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 111
 112        if (!ret && oact) {
 113                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 114                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
 115                    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
 116                    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
 117                    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
 118                        return -EFAULT;
 119        }
 120
 121        return ret;
 122}
 123
 124asmlinkage int
 125sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
 126{
 127        return do_sigaltstack(uss, uoss, rdusp());
 128}
 129
 130
 131/*
 132 * Do a signal return; undo the signal stack.
 133 *
 134 * Keep the return code on the stack quadword aligned!
 135 * That makes the cache flush below easier.
 136 */
 137
 138struct sigframe
 139{
 140        char __user *pretcode;
 141        int sig;
 142        int code;
 143        struct sigcontext __user *psc;
 144        char retcode[8];
 145        unsigned long extramask[_NSIG_WORDS-1];
 146        struct sigcontext sc;
 147};
 148
 149struct rt_sigframe
 150{
 151        char __user *pretcode;
 152        int sig;
 153        struct siginfo __user *pinfo;
 154        void __user *puc;
 155        char retcode[8];
 156        struct siginfo info;
 157        struct ucontext uc;
 158};
 159
 160
 161static unsigned char fpu_version;       /* version number of fpu, set by setup_frame */
 162
 163static inline int restore_fpu_state(struct sigcontext *sc)
 164{
 165        int err = 1;
 166
 167        if (FPU_IS_EMU) {
 168            /* restore registers */
 169            memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
 170            memcpy(current->thread.fp, sc->sc_fpregs, 24);
 171            return 0;
 172        }
 173
 174        if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
 175            /* Verify the frame format.  */
 176            if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
 177                goto out;
 178            if (CPU_IS_020_OR_030) {
 179                if (m68k_fputype & FPU_68881 &&
 180                    !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
 181                    goto out;
 182                if (m68k_fputype & FPU_68882 &&
 183                    !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
 184                    goto out;
 185            } else if (CPU_IS_040) {
 186                if (!(sc->sc_fpstate[1] == 0x00 ||
 187                      sc->sc_fpstate[1] == 0x28 ||
 188                      sc->sc_fpstate[1] == 0x60))
 189                    goto out;
 190            } else if (CPU_IS_060) {
 191                if (!(sc->sc_fpstate[3] == 0x00 ||
 192                      sc->sc_fpstate[3] == 0x60 ||
 193                      sc->sc_fpstate[3] == 0xe0))
 194                    goto out;
 195            } else
 196                goto out;
 197
 198            __asm__ volatile (".chip 68k/68881\n\t"
 199                              "fmovemx %0,%%fp0-%%fp1\n\t"
 200                              "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
 201                              ".chip 68k"
 202                              : /* no outputs */
 203                              : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
 204        }
 205        __asm__ volatile (".chip 68k/68881\n\t"
 206                          "frestore %0\n\t"
 207                          ".chip 68k" : : "m" (*sc->sc_fpstate));
 208        err = 0;
 209
 210out:
 211        return err;
 212}
 213
 214#define FPCONTEXT_SIZE  216
 215#define uc_fpstate      uc_filler[0]
 216#define uc_formatvec    uc_filler[FPCONTEXT_SIZE/4]
 217#define uc_extra        uc_filler[FPCONTEXT_SIZE/4+1]
 218
 219static inline int rt_restore_fpu_state(struct ucontext __user *uc)
 220{
 221        unsigned char fpstate[FPCONTEXT_SIZE];
 222        int context_size = CPU_IS_060 ? 8 : 0;
 223        fpregset_t fpregs;
 224        int err = 1;
 225
 226        if (FPU_IS_EMU) {
 227                /* restore fpu control register */
 228                if (__copy_from_user(current->thread.fpcntl,
 229                                uc->uc_mcontext.fpregs.f_fpcntl, 12))
 230                        goto out;
 231                /* restore all other fpu register */
 232                if (__copy_from_user(current->thread.fp,
 233                                uc->uc_mcontext.fpregs.f_fpregs, 96))
 234                        goto out;
 235                return 0;
 236        }
 237
 238        if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
 239                goto out;
 240        if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
 241                if (!CPU_IS_060)
 242                        context_size = fpstate[1];
 243                /* Verify the frame format.  */
 244                if (!CPU_IS_060 && (fpstate[0] != fpu_version))
 245                        goto out;
 246                if (CPU_IS_020_OR_030) {
 247                        if (m68k_fputype & FPU_68881 &&
 248                            !(context_size == 0x18 || context_size == 0xb4))
 249                                goto out;
 250                        if (m68k_fputype & FPU_68882 &&
 251                            !(context_size == 0x38 || context_size == 0xd4))
 252                                goto out;
 253                } else if (CPU_IS_040) {
 254                        if (!(context_size == 0x00 ||
 255                              context_size == 0x28 ||
 256                              context_size == 0x60))
 257                                goto out;
 258                } else if (CPU_IS_060) {
 259                        if (!(fpstate[3] == 0x00 ||
 260                              fpstate[3] == 0x60 ||
 261                              fpstate[3] == 0xe0))
 262                                goto out;
 263                } else
 264                        goto out;
 265                if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
 266                                     sizeof(fpregs)))
 267                        goto out;
 268                __asm__ volatile (".chip 68k/68881\n\t"
 269                                  "fmovemx %0,%%fp0-%%fp7\n\t"
 270                                  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
 271                                  ".chip 68k"
 272                                  : /* no outputs */
 273                                  : "m" (*fpregs.f_fpregs),
 274                                    "m" (*fpregs.f_fpcntl));
 275        }
 276        if (context_size &&
 277            __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
 278                             context_size))
 279                goto out;
 280        __asm__ volatile (".chip 68k/68881\n\t"
 281                          "frestore %0\n\t"
 282                          ".chip 68k" : : "m" (*fpstate));
 283        err = 0;
 284
 285out:
 286        return err;
 287}
 288
 289static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
 290                               void __user *fp)
 291{
 292        int fsize = frame_extra_sizes[formatvec >> 12];
 293        if (fsize < 0) {
 294                /*
 295                 * user process trying to return with weird frame format
 296                 */
 297#ifdef DEBUG
 298                printk("user process returning with weird frame format\n");
 299#endif
 300                return 1;
 301        }
 302        if (!fsize) {
 303                regs->format = formatvec >> 12;
 304                regs->vector = formatvec & 0xfff;
 305        } else {
 306                struct switch_stack *sw = (struct switch_stack *)regs - 1;
 307                unsigned long buf[fsize / 2]; /* yes, twice as much */
 308
 309                /* that'll make sure that expansion won't crap over data */
 310                if (copy_from_user(buf + fsize / 4, fp, fsize))
 311                        return 1;
 312
 313                /* point of no return */
 314                regs->format = formatvec >> 12;
 315                regs->vector = formatvec & 0xfff;
 316#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
 317                __asm__ __volatile__
 318                        ("   movel %0,%/a0\n\t"
 319                         "   subl %1,%/a0\n\t"     /* make room on stack */
 320                         "   movel %/a0,%/sp\n\t"  /* set stack pointer */
 321                         /* move switch_stack and pt_regs */
 322                         "1: movel %0@+,%/a0@+\n\t"
 323                         "   dbra %2,1b\n\t"
 324                         "   lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
 325                         "   lsrl  #2,%1\n\t"
 326                         "   subql #1,%1\n\t"
 327                         /* copy to the gap we'd made */
 328                         "2: movel %4@+,%/a0@+\n\t"
 329                         "   dbra %1,2b\n\t"
 330                         "   bral ret_from_signal\n"
 331                         : /* no outputs, it doesn't ever return */
 332                         : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
 333                           "n" (frame_offset), "a" (buf + fsize/4)
 334                         : "a0");
 335#undef frame_offset
 336        }
 337        return 0;
 338}
 339
 340static inline int
 341restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
 342{
 343        int formatvec;
 344        struct sigcontext context;
 345        int err;
 346
 347        /* Always make any pending restarted system calls return -EINTR */
 348        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 349
 350        /* get previous context */
 351        if (copy_from_user(&context, usc, sizeof(context)))
 352                goto badframe;
 353
 354        /* restore passed registers */
 355        regs->d0 = context.sc_d0;
 356        regs->d1 = context.sc_d1;
 357        regs->a0 = context.sc_a0;
 358        regs->a1 = context.sc_a1;
 359        regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
 360        regs->pc = context.sc_pc;
 361        regs->orig_d0 = -1;             /* disable syscall checks */
 362        wrusp(context.sc_usp);
 363        formatvec = context.sc_formatvec;
 364
 365        err = restore_fpu_state(&context);
 366
 367        if (err || mangle_kernel_stack(regs, formatvec, fp))
 368                goto badframe;
 369
 370        return 0;
 371
 372badframe:
 373        return 1;
 374}
 375
 376static inline int
 377rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
 378                    struct ucontext __user *uc)
 379{
 380        int temp;
 381        greg_t __user *gregs = uc->uc_mcontext.gregs;
 382        unsigned long usp;
 383        int err;
 384
 385        /* Always make any pending restarted system calls return -EINTR */
 386        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 387
 388        err = __get_user(temp, &uc->uc_mcontext.version);
 389        if (temp != MCONTEXT_VERSION)
 390                goto badframe;
 391        /* restore passed registers */
 392        err |= __get_user(regs->d0, &gregs[0]);
 393        err |= __get_user(regs->d1, &gregs[1]);
 394        err |= __get_user(regs->d2, &gregs[2]);
 395        err |= __get_user(regs->d3, &gregs[3]);
 396        err |= __get_user(regs->d4, &gregs[4]);
 397        err |= __get_user(regs->d5, &gregs[5]);
 398        err |= __get_user(sw->d6, &gregs[6]);
 399        err |= __get_user(sw->d7, &gregs[7]);
 400        err |= __get_user(regs->a0, &gregs[8]);
 401        err |= __get_user(regs->a1, &gregs[9]);
 402        err |= __get_user(regs->a2, &gregs[10]);
 403        err |= __get_user(sw->a3, &gregs[11]);
 404        err |= __get_user(sw->a4, &gregs[12]);
 405        err |= __get_user(sw->a5, &gregs[13]);
 406        err |= __get_user(sw->a6, &gregs[14]);
 407        err |= __get_user(usp, &gregs[15]);
 408        wrusp(usp);
 409        err |= __get_user(regs->pc, &gregs[16]);
 410        err |= __get_user(temp, &gregs[17]);
 411        regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
 412        regs->orig_d0 = -1;             /* disable syscall checks */
 413        err |= __get_user(temp, &uc->uc_formatvec);
 414
 415        err |= rt_restore_fpu_state(uc);
 416
 417        if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
 418                goto badframe;
 419
 420        if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
 421                goto badframe;
 422
 423        return 0;
 424
 425badframe:
 426        return 1;
 427}
 428
 429asmlinkage int do_sigreturn(unsigned long __unused)
 430{
 431        struct switch_stack *sw = (struct switch_stack *) &__unused;
 432        struct pt_regs *regs = (struct pt_regs *) (sw + 1);
 433        unsigned long usp = rdusp();
 434        struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
 435        sigset_t set;
 436
 437        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 438                goto badframe;
 439        if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
 440            (_NSIG_WORDS > 1 &&
 441             __copy_from_user(&set.sig[1], &frame->extramask,
 442                              sizeof(frame->extramask))))
 443                goto badframe;
 444
 445        sigdelsetmask(&set, ~_BLOCKABLE);
 446        current->blocked = set;
 447        recalc_sigpending();
 448
 449        if (restore_sigcontext(regs, &frame->sc, frame + 1))
 450                goto badframe;
 451        return regs->d0;
 452
 453badframe:
 454        force_sig(SIGSEGV, current);
 455        return 0;
 456}
 457
 458asmlinkage int do_rt_sigreturn(unsigned long __unused)
 459{
 460        struct switch_stack *sw = (struct switch_stack *) &__unused;
 461        struct pt_regs *regs = (struct pt_regs *) (sw + 1);
 462        unsigned long usp = rdusp();
 463        struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
 464        sigset_t set;
 465
 466        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 467                goto badframe;
 468        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 469                goto badframe;
 470
 471        sigdelsetmask(&set, ~_BLOCKABLE);
 472        current->blocked = set;
 473        recalc_sigpending();
 474
 475        if (rt_restore_ucontext(regs, sw, &frame->uc))
 476                goto badframe;
 477        return regs->d0;
 478
 479badframe:
 480        force_sig(SIGSEGV, current);
 481        return 0;
 482}
 483
 484/*
 485 * Set up a signal frame.
 486 */
 487
 488static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
 489{
 490        if (FPU_IS_EMU) {
 491                /* save registers */
 492                memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
 493                memcpy(sc->sc_fpregs, current->thread.fp, 24);
 494                return;
 495        }
 496
 497        __asm__ volatile (".chip 68k/68881\n\t"
 498                          "fsave %0\n\t"
 499                          ".chip 68k"
 500                          : : "m" (*sc->sc_fpstate) : "memory");
 501
 502        if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
 503                fpu_version = sc->sc_fpstate[0];
 504                if (CPU_IS_020_OR_030 &&
 505                    regs->vector >= (VEC_FPBRUC * 4) &&
 506                    regs->vector <= (VEC_FPNAN * 4)) {
 507                        /* Clear pending exception in 68882 idle frame */
 508                        if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
 509                                sc->sc_fpstate[0x38] |= 1 << 3;
 510                }
 511                __asm__ volatile (".chip 68k/68881\n\t"
 512                                  "fmovemx %%fp0-%%fp1,%0\n\t"
 513                                  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
 514                                  ".chip 68k"
 515                                  : "=m" (*sc->sc_fpregs),
 516                                    "=m" (*sc->sc_fpcntl)
 517                                  : /* no inputs */
 518                                  : "memory");
 519        }
 520}
 521
 522static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
 523{
 524        unsigned char fpstate[FPCONTEXT_SIZE];
 525        int context_size = CPU_IS_060 ? 8 : 0;
 526        int err = 0;
 527
 528        if (FPU_IS_EMU) {
 529                /* save fpu control register */
 530                err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
 531                                current->thread.fpcntl, 12);
 532                /* save all other fpu register */
 533                err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
 534                                current->thread.fp, 96);
 535                return err;
 536        }
 537
 538        __asm__ volatile (".chip 68k/68881\n\t"
 539                          "fsave %0\n\t"
 540                          ".chip 68k"
 541                          : : "m" (*fpstate) : "memory");
 542
 543        err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
 544        if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
 545                fpregset_t fpregs;
 546                if (!CPU_IS_060)
 547                        context_size = fpstate[1];
 548                fpu_version = fpstate[0];
 549                if (CPU_IS_020_OR_030 &&
 550                    regs->vector >= (VEC_FPBRUC * 4) &&
 551                    regs->vector <= (VEC_FPNAN * 4)) {
 552                        /* Clear pending exception in 68882 idle frame */
 553                        if (*(unsigned short *) fpstate == 0x1f38)
 554                                fpstate[0x38] |= 1 << 3;
 555                }
 556                __asm__ volatile (".chip 68k/68881\n\t"
 557                                  "fmovemx %%fp0-%%fp7,%0\n\t"
 558                                  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
 559                                  ".chip 68k"
 560                                  : "=m" (*fpregs.f_fpregs),
 561                                    "=m" (*fpregs.f_fpcntl)
 562                                  : /* no inputs */
 563                                  : "memory");
 564                err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
 565                                    sizeof(fpregs));
 566        }
 567        if (context_size)
 568                err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
 569                                    context_size);
 570        return err;
 571}
 572
 573static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
 574                             unsigned long mask)
 575{
 576        sc->sc_mask = mask;
 577        sc->sc_usp = rdusp();
 578        sc->sc_d0 = regs->d0;
 579        sc->sc_d1 = regs->d1;
 580        sc->sc_a0 = regs->a0;
 581        sc->sc_a1 = regs->a1;
 582        sc->sc_sr = regs->sr;
 583        sc->sc_pc = regs->pc;
 584        sc->sc_formatvec = regs->format << 12 | regs->vector;
 585        save_fpu_state(sc, regs);
 586}
 587
 588static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
 589{
 590        struct switch_stack *sw = (struct switch_stack *)regs - 1;
 591        greg_t __user *gregs = uc->uc_mcontext.gregs;
 592        int err = 0;
 593
 594        err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
 595        err |= __put_user(regs->d0, &gregs[0]);
 596        err |= __put_user(regs->d1, &gregs[1]);
 597        err |= __put_user(regs->d2, &gregs[2]);
 598        err |= __put_user(regs->d3, &gregs[3]);
 599        err |= __put_user(regs->d4, &gregs[4]);
 600        err |= __put_user(regs->d5, &gregs[5]);
 601        err |= __put_user(sw->d6, &gregs[6]);
 602        err |= __put_user(sw->d7, &gregs[7]);
 603        err |= __put_user(regs->a0, &gregs[8]);
 604        err |= __put_user(regs->a1, &gregs[9]);
 605        err |= __put_user(regs->a2, &gregs[10]);
 606        err |= __put_user(sw->a3, &gregs[11]);
 607        err |= __put_user(sw->a4, &gregs[12]);
 608        err |= __put_user(sw->a5, &gregs[13]);
 609        err |= __put_user(sw->a6, &gregs[14]);
 610        err |= __put_user(rdusp(), &gregs[15]);
 611        err |= __put_user(regs->pc, &gregs[16]);
 612        err |= __put_user(regs->sr, &gregs[17]);
 613        err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
 614        err |= rt_save_fpu_state(uc, regs);
 615        return err;
 616}
 617
 618static inline void push_cache (unsigned long vaddr)
 619{
 620        /*
 621         * Using the old cache_push_v() was really a big waste.
 622         *
 623         * What we are trying to do is to flush 8 bytes to ram.
 624         * Flushing 2 cache lines of 16 bytes is much cheaper than
 625         * flushing 1 or 2 pages, as previously done in
 626         * cache_push_v().
 627         *                                                     Jes
 628         */
 629        if (CPU_IS_040) {
 630                unsigned long temp;
 631
 632                __asm__ __volatile__ (".chip 68040\n\t"
 633                                      "nop\n\t"
 634                                      "ptestr (%1)\n\t"
 635                                      "movec %%mmusr,%0\n\t"
 636                                      ".chip 68k"
 637                                      : "=r" (temp)
 638                                      : "a" (vaddr));
 639
 640                temp &= PAGE_MASK;
 641                temp |= vaddr & ~PAGE_MASK;
 642
 643                __asm__ __volatile__ (".chip 68040\n\t"
 644                                      "nop\n\t"
 645                                      "cpushl %%bc,(%0)\n\t"
 646                                      ".chip 68k"
 647                                      : : "a" (temp));
 648        }
 649        else if (CPU_IS_060) {
 650                unsigned long temp;
 651                __asm__ __volatile__ (".chip 68060\n\t"
 652                                      "plpar (%0)\n\t"
 653                                      ".chip 68k"
 654                                      : "=a" (temp)
 655                                      : "0" (vaddr));
 656                __asm__ __volatile__ (".chip 68060\n\t"
 657                                      "cpushl %%bc,(%0)\n\t"
 658                                      ".chip 68k"
 659                                      : : "a" (temp));
 660        }
 661        else {
 662                /*
 663                 * 68030/68020 have no writeback cache;
 664                 * still need to clear icache.
 665                 * Note that vaddr is guaranteed to be long word aligned.
 666                 */
 667                unsigned long temp;
 668                asm volatile ("movec %%cacr,%0" : "=r" (temp));
 669                temp += 4;
 670                asm volatile ("movec %0,%%caar\n\t"
 671                              "movec %1,%%cacr"
 672                              : : "r" (vaddr), "r" (temp));
 673                asm volatile ("movec %0,%%caar\n\t"
 674                              "movec %1,%%cacr"
 675                              : : "r" (vaddr + 4), "r" (temp));
 676        }
 677}
 678
 679static inline void __user *
 680get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 681{
 682        unsigned long usp;
 683
 684        /* Default to using normal stack.  */
 685        usp = rdusp();
 686
 687        /* This is the X/Open sanctioned signal stack switching.  */
 688        if (ka->sa.sa_flags & SA_ONSTACK) {
 689                if (!sas_ss_flags(usp))
 690                        usp = current->sas_ss_sp + current->sas_ss_size;
 691        }
 692        return (void __user *)((usp - frame_size) & -8UL);
 693}
 694
 695static int setup_frame (int sig, struct k_sigaction *ka,
 696                         sigset_t *set, struct pt_regs *regs)
 697{
 698        struct sigframe __user *frame;
 699        int fsize = frame_extra_sizes[regs->format];
 700        struct sigcontext context;
 701        int err = 0;
 702
 703        if (fsize < 0) {
 704#ifdef DEBUG
 705                printk ("setup_frame: Unknown frame format %#x\n",
 706                        regs->format);
 707#endif
 708                goto give_sigsegv;
 709        }
 710
 711        frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
 712
 713        if (fsize)
 714                err |= copy_to_user (frame + 1, regs + 1, fsize);
 715
 716        err |= __put_user((current_thread_info()->exec_domain
 717                           && current_thread_info()->exec_domain->signal_invmap
 718                           && sig < 32
 719                           ? current_thread_info()->exec_domain->signal_invmap[sig]
 720                           : sig),
 721                          &frame->sig);
 722
 723        err |= __put_user(regs->vector, &frame->code);
 724        err |= __put_user(&frame->sc, &frame->psc);
 725
 726        if (_NSIG_WORDS > 1)
 727                err |= copy_to_user(frame->extramask, &set->sig[1],
 728                                    sizeof(frame->extramask));
 729
 730        setup_sigcontext(&context, regs, set->sig[0]);
 731        err |= copy_to_user (&frame->sc, &context, sizeof(context));
 732
 733        /* Set up to return from userspace.  */
 734        err |= __put_user(frame->retcode, &frame->pretcode);
 735        /* moveq #,d0; trap #0 */
 736        err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
 737                          (long __user *)(frame->retcode));
 738
 739        if (err)
 740                goto give_sigsegv;
 741
 742        push_cache ((unsigned long) &frame->retcode);
 743
 744        /*
 745         * Set up registers for signal handler.  All the state we are about
 746         * to destroy is successfully copied to sigframe.
 747         */
 748        wrusp ((unsigned long) frame);
 749        regs->pc = (unsigned long) ka->sa.sa_handler;
 750
 751        /*
 752         * This is subtle; if we build more than one sigframe, all but the
 753         * first one will see frame format 0 and have fsize == 0, so we won't
 754         * screw stkadj.
 755         */
 756        if (fsize)
 757                regs->stkadj = fsize;
 758
 759        /* Prepare to skip over the extra stuff in the exception frame.  */
 760        if (regs->stkadj) {
 761                struct pt_regs *tregs =
 762                        (struct pt_regs *)((ulong)regs + regs->stkadj);
 763#ifdef DEBUG
 764                printk("Performing stackadjust=%04x\n", regs->stkadj);
 765#endif
 766                /* This must be copied with decreasing addresses to
 767                   handle overlaps.  */
 768                tregs->vector = 0;
 769                tregs->format = 0;
 770                tregs->pc = regs->pc;
 771                tregs->sr = regs->sr;
 772        }
 773        return 0;
 774
 775give_sigsegv:
 776        force_sigsegv(sig, current);
 777        return err;
 778}
 779
 780static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
 781                            sigset_t *set, struct pt_regs *regs)
 782{
 783        struct rt_sigframe __user *frame;
 784        int fsize = frame_extra_sizes[regs->format];
 785        int err = 0;
 786
 787        if (fsize < 0) {
 788#ifdef DEBUG
 789                printk ("setup_frame: Unknown frame format %#x\n",
 790                        regs->format);
 791#endif
 792                goto give_sigsegv;
 793        }
 794
 795        frame = get_sigframe(ka, regs, sizeof(*frame));
 796
 797        if (fsize)
 798                err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
 799
 800        err |= __put_user((current_thread_info()->exec_domain
 801                           && current_thread_info()->exec_domain->signal_invmap
 802                           && sig < 32
 803                           ? current_thread_info()->exec_domain->signal_invmap[sig]
 804                           : sig),
 805                          &frame->sig);
 806        err |= __put_user(&frame->info, &frame->pinfo);
 807        err |= __put_user(&frame->uc, &frame->puc);
 808        err |= copy_siginfo_to_user(&frame->info, info);
 809
 810        /* Create the ucontext.  */
 811        err |= __put_user(0, &frame->uc.uc_flags);
 812        err |= __put_user(NULL, &frame->uc.uc_link);
 813        err |= __put_user((void __user *)current->sas_ss_sp,
 814                          &frame->uc.uc_stack.ss_sp);
 815        err |= __put_user(sas_ss_flags(rdusp()),
 816                          &frame->uc.uc_stack.ss_flags);
 817        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
 818        err |= rt_setup_ucontext(&frame->uc, regs);
 819        err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
 820
 821        /* Set up to return from userspace.  */
 822        err |= __put_user(frame->retcode, &frame->pretcode);
 823#ifdef __mcoldfire__
 824        /* movel #__NR_rt_sigreturn,d0; trap #0 */
 825        err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0));
 826        err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16),
 827                          (long __user *)(frame->retcode + 4));
 828#else
 829        /* moveq #,d0; notb d0; trap #0 */
 830        err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
 831                          (long __user *)(frame->retcode + 0));
 832        err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));
 833#endif
 834
 835        if (err)
 836                goto give_sigsegv;
 837
 838        push_cache ((unsigned long) &frame->retcode);
 839
 840        /*
 841         * Set up registers for signal handler.  All the state we are about
 842         * to destroy is successfully copied to sigframe.
 843         */
 844        wrusp ((unsigned long) frame);
 845        regs->pc = (unsigned long) ka->sa.sa_handler;
 846
 847        /*
 848         * This is subtle; if we build more than one sigframe, all but the
 849         * first one will see frame format 0 and have fsize == 0, so we won't
 850         * screw stkadj.
 851         */
 852        if (fsize)
 853                regs->stkadj = fsize;
 854
 855        /* Prepare to skip over the extra stuff in the exception frame.  */
 856        if (regs->stkadj) {
 857                struct pt_regs *tregs =
 858                        (struct pt_regs *)((ulong)regs + regs->stkadj);
 859#ifdef DEBUG
 860                printk("Performing stackadjust=%04x\n", regs->stkadj);
 861#endif
 862                /* This must be copied with decreasing addresses to
 863                   handle overlaps.  */
 864                tregs->vector = 0;
 865                tregs->format = 0;
 866                tregs->pc = regs->pc;
 867                tregs->sr = regs->sr;
 868        }
 869        return 0;
 870
 871give_sigsegv:
 872        force_sigsegv(sig, current);
 873        return err;
 874}
 875
 876static inline void
 877handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
 878{
 879        switch (regs->d0) {
 880        case -ERESTARTNOHAND:
 881                if (!has_handler)
 882                        goto do_restart;
 883                regs->d0 = -EINTR;
 884                break;
 885
 886        case -ERESTART_RESTARTBLOCK:
 887                if (!has_handler) {
 888                        regs->d0 = __NR_restart_syscall;
 889                        regs->pc -= 2;
 890                        break;
 891                }
 892                regs->d0 = -EINTR;
 893                break;
 894
 895        case -ERESTARTSYS:
 896                if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
 897                        regs->d0 = -EINTR;
 898                        break;
 899                }
 900        /* fallthrough */
 901        case -ERESTARTNOINTR:
 902        do_restart:
 903                regs->d0 = regs->orig_d0;
 904                regs->pc -= 2;
 905                break;
 906        }
 907}
 908
 909void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
 910{
 911        if (regs->orig_d0 < 0)
 912                return;
 913        switch (regs->d0) {
 914        case -ERESTARTNOHAND:
 915        case -ERESTARTSYS:
 916        case -ERESTARTNOINTR:
 917                regs->d0 = regs->orig_d0;
 918                regs->orig_d0 = -1;
 919                regs->pc -= 2;
 920                break;
 921        }
 922}
 923
 924/*
 925 * OK, we're invoking a handler
 926 */
 927static void
 928handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
 929              sigset_t *oldset, struct pt_regs *regs)
 930{
 931        int err;
 932        /* are we from a system call? */
 933        if (regs->orig_d0 >= 0)
 934                /* If so, check system call restarting.. */
 935                handle_restart(regs, ka, 1);
 936
 937        /* set up the stack frame */
 938        if (ka->sa.sa_flags & SA_SIGINFO)
 939                err = setup_rt_frame(sig, ka, info, oldset, regs);
 940        else
 941                err = setup_frame(sig, ka, oldset, regs);
 942
 943        if (err)
 944                return;
 945
 946        sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 947        if (!(ka->sa.sa_flags & SA_NODEFER))
 948                sigaddset(&current->blocked,sig);
 949        recalc_sigpending();
 950
 951        if (test_thread_flag(TIF_DELAYED_TRACE)) {
 952                regs->sr &= ~0x8000;
 953                send_sig(SIGTRAP, current, 1);
 954        }
 955
 956        clear_thread_flag(TIF_RESTORE_SIGMASK);
 957}
 958
 959/*
 960 * Note that 'init' is a special process: it doesn't get signals it doesn't
 961 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 962 * mistake.
 963 */
 964asmlinkage void do_signal(struct pt_regs *regs)
 965{
 966        siginfo_t info;
 967        struct k_sigaction ka;
 968        int signr;
 969        sigset_t *oldset;
 970
 971        current->thread.esp0 = (unsigned long) regs;
 972
 973        if (test_thread_flag(TIF_RESTORE_SIGMASK))
 974                oldset = &current->saved_sigmask;
 975        else
 976                oldset = &current->blocked;
 977
 978        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 979        if (signr > 0) {
 980                /* Whee!  Actually deliver the signal.  */
 981                handle_signal(signr, &ka, &info, oldset, regs);
 982                return;
 983        }
 984
 985        /* Did we come from a system call? */
 986        if (regs->orig_d0 >= 0)
 987                /* Restart the system call - no handlers present */
 988                handle_restart(regs, NULL, 0);
 989
 990        /* If there's no signal to deliver, we just restore the saved mask.  */
 991        if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
 992                clear_thread_flag(TIF_RESTORE_SIGMASK);
 993                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 994        }
 995}
 996