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