linux/arch/m68k/kernel/traps.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/m68k/kernel/traps.c
   3 *
   4 *  Copyright (C) 1993, 1994 by Hamish Macdonald
   5 *
   6 *  68040 fixes by Michael Rausch
   7 *  68040 fixes by Martin Apel
   8 *  68040 fixes and writeback by Richard Zidlicky
   9 *  68060 fixes by Roman Hodek
  10 *  68060 fixes by Jesper Skov
  11 *
  12 * This file is subject to the terms and conditions of the GNU General Public
  13 * License.  See the file COPYING in the main directory of this archive
  14 * for more details.
  15 */
  16
  17/*
  18 * Sets up all exception vectors
  19 */
  20
  21#include <linux/sched.h>
  22#include <linux/signal.h>
  23#include <linux/kernel.h>
  24#include <linux/mm.h>
  25#include <linux/module.h>
  26#include <linux/user.h>
  27#include <linux/string.h>
  28#include <linux/linkage.h>
  29#include <linux/init.h>
  30#include <linux/ptrace.h>
  31#include <linux/kallsyms.h>
  32
  33#include <asm/setup.h>
  34#include <asm/fpu.h>
  35#include <asm/system.h>
  36#include <asm/uaccess.h>
  37#include <asm/traps.h>
  38#include <asm/pgalloc.h>
  39#include <asm/machdep.h>
  40#include <asm/siginfo.h>
  41
  42/* assembler routines */
  43asmlinkage void system_call(void);
  44asmlinkage void buserr(void);
  45asmlinkage void trap(void);
  46asmlinkage void nmihandler(void);
  47#ifdef CONFIG_M68KFPU_EMU
  48asmlinkage void fpu_emu(void);
  49#endif
  50
  51e_vector vectors[256] = {
  52        [VEC_BUSERR]    = buserr,
  53        [VEC_SYS]       = system_call,
  54};
  55
  56/* nmi handler for the Amiga */
  57asm(".text\n"
  58    __ALIGN_STR "\n"
  59    "nmihandler: rte");
  60
  61/*
  62 * this must be called very early as the kernel might
  63 * use some instruction that are emulated on the 060
  64 */
  65void __init base_trap_init(void)
  66{
  67        if(MACH_IS_SUN3X) {
  68                extern e_vector *sun3x_prom_vbr;
  69
  70                __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
  71        }
  72
  73        /* setup the exception vector table */
  74        __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
  75
  76        if (CPU_IS_060) {
  77                /* set up ISP entry points */
  78                asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
  79
  80                vectors[VEC_UNIMPII] = unimp_vec;
  81        }
  82}
  83
  84void __init trap_init (void)
  85{
  86        int i;
  87
  88        for (i = VEC_SPUR; i <= VEC_INT7; i++)
  89                vectors[i] = bad_inthandler;
  90
  91        for (i = 0; i < VEC_USER; i++)
  92                if (!vectors[i])
  93                        vectors[i] = trap;
  94
  95        for (i = VEC_USER; i < 256; i++)
  96                vectors[i] = bad_inthandler;
  97
  98#ifdef CONFIG_M68KFPU_EMU
  99        if (FPU_IS_EMU)
 100                vectors[VEC_LINE11] = fpu_emu;
 101#endif
 102
 103        if (CPU_IS_040 && !FPU_IS_EMU) {
 104                /* set up FPSP entry points */
 105                asmlinkage void dz_vec(void) asm ("dz");
 106                asmlinkage void inex_vec(void) asm ("inex");
 107                asmlinkage void ovfl_vec(void) asm ("ovfl");
 108                asmlinkage void unfl_vec(void) asm ("unfl");
 109                asmlinkage void snan_vec(void) asm ("snan");
 110                asmlinkage void operr_vec(void) asm ("operr");
 111                asmlinkage void bsun_vec(void) asm ("bsun");
 112                asmlinkage void fline_vec(void) asm ("fline");
 113                asmlinkage void unsupp_vec(void) asm ("unsupp");
 114
 115                vectors[VEC_FPDIVZ] = dz_vec;
 116                vectors[VEC_FPIR] = inex_vec;
 117                vectors[VEC_FPOVER] = ovfl_vec;
 118                vectors[VEC_FPUNDER] = unfl_vec;
 119                vectors[VEC_FPNAN] = snan_vec;
 120                vectors[VEC_FPOE] = operr_vec;
 121                vectors[VEC_FPBRUC] = bsun_vec;
 122                vectors[VEC_LINE11] = fline_vec;
 123                vectors[VEC_FPUNSUP] = unsupp_vec;
 124        }
 125
 126        if (CPU_IS_060 && !FPU_IS_EMU) {
 127                /* set up IFPSP entry points */
 128                asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
 129                asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
 130                asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
 131                asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
 132                asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
 133                asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
 134                asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
 135                asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
 136                asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
 137
 138                vectors[VEC_FPNAN] = snan_vec6;
 139                vectors[VEC_FPOE] = operr_vec6;
 140                vectors[VEC_FPOVER] = ovfl_vec6;
 141                vectors[VEC_FPUNDER] = unfl_vec6;
 142                vectors[VEC_FPDIVZ] = dz_vec6;
 143                vectors[VEC_FPIR] = inex_vec6;
 144                vectors[VEC_LINE11] = fline_vec6;
 145                vectors[VEC_FPUNSUP] = unsupp_vec6;
 146                vectors[VEC_UNIMPEA] = effadd_vec6;
 147        }
 148
 149        /* if running on an amiga, make the NMI interrupt do nothing */
 150        if (MACH_IS_AMIGA) {
 151                vectors[VEC_INT7] = nmihandler;
 152        }
 153}
 154
 155
 156static const char *vec_names[] = {
 157        [VEC_RESETSP]   = "RESET SP",
 158        [VEC_RESETPC]   = "RESET PC",
 159        [VEC_BUSERR]    = "BUS ERROR",
 160        [VEC_ADDRERR]   = "ADDRESS ERROR",
 161        [VEC_ILLEGAL]   = "ILLEGAL INSTRUCTION",
 162        [VEC_ZERODIV]   = "ZERO DIVIDE",
 163        [VEC_CHK]       = "CHK",
 164        [VEC_TRAP]      = "TRAPcc",
 165        [VEC_PRIV]      = "PRIVILEGE VIOLATION",
 166        [VEC_TRACE]     = "TRACE",
 167        [VEC_LINE10]    = "LINE 1010",
 168        [VEC_LINE11]    = "LINE 1111",
 169        [VEC_RESV12]    = "UNASSIGNED RESERVED 12",
 170        [VEC_COPROC]    = "COPROCESSOR PROTOCOL VIOLATION",
 171        [VEC_FORMAT]    = "FORMAT ERROR",
 172        [VEC_UNINT]     = "UNINITIALIZED INTERRUPT",
 173        [VEC_RESV16]    = "UNASSIGNED RESERVED 16",
 174        [VEC_RESV17]    = "UNASSIGNED RESERVED 17",
 175        [VEC_RESV18]    = "UNASSIGNED RESERVED 18",
 176        [VEC_RESV19]    = "UNASSIGNED RESERVED 19",
 177        [VEC_RESV20]    = "UNASSIGNED RESERVED 20",
 178        [VEC_RESV21]    = "UNASSIGNED RESERVED 21",
 179        [VEC_RESV22]    = "UNASSIGNED RESERVED 22",
 180        [VEC_RESV23]    = "UNASSIGNED RESERVED 23",
 181        [VEC_SPUR]      = "SPURIOUS INTERRUPT",
 182        [VEC_INT1]      = "LEVEL 1 INT",
 183        [VEC_INT2]      = "LEVEL 2 INT",
 184        [VEC_INT3]      = "LEVEL 3 INT",
 185        [VEC_INT4]      = "LEVEL 4 INT",
 186        [VEC_INT5]      = "LEVEL 5 INT",
 187        [VEC_INT6]      = "LEVEL 6 INT",
 188        [VEC_INT7]      = "LEVEL 7 INT",
 189        [VEC_SYS]       = "SYSCALL",
 190        [VEC_TRAP1]     = "TRAP #1",
 191        [VEC_TRAP2]     = "TRAP #2",
 192        [VEC_TRAP3]     = "TRAP #3",
 193        [VEC_TRAP4]     = "TRAP #4",
 194        [VEC_TRAP5]     = "TRAP #5",
 195        [VEC_TRAP6]     = "TRAP #6",
 196        [VEC_TRAP7]     = "TRAP #7",
 197        [VEC_TRAP8]     = "TRAP #8",
 198        [VEC_TRAP9]     = "TRAP #9",
 199        [VEC_TRAP10]    = "TRAP #10",
 200        [VEC_TRAP11]    = "TRAP #11",
 201        [VEC_TRAP12]    = "TRAP #12",
 202        [VEC_TRAP13]    = "TRAP #13",
 203        [VEC_TRAP14]    = "TRAP #14",
 204        [VEC_TRAP15]    = "TRAP #15",
 205        [VEC_FPBRUC]    = "FPCP BSUN",
 206        [VEC_FPIR]      = "FPCP INEXACT",
 207        [VEC_FPDIVZ]    = "FPCP DIV BY 0",
 208        [VEC_FPUNDER]   = "FPCP UNDERFLOW",
 209        [VEC_FPOE]      = "FPCP OPERAND ERROR",
 210        [VEC_FPOVER]    = "FPCP OVERFLOW",
 211        [VEC_FPNAN]     = "FPCP SNAN",
 212        [VEC_FPUNSUP]   = "FPCP UNSUPPORTED OPERATION",
 213        [VEC_MMUCFG]    = "MMU CONFIGURATION ERROR",
 214        [VEC_MMUILL]    = "MMU ILLEGAL OPERATION ERROR",
 215        [VEC_MMUACC]    = "MMU ACCESS LEVEL VIOLATION ERROR",
 216        [VEC_RESV59]    = "UNASSIGNED RESERVED 59",
 217        [VEC_UNIMPEA]   = "UNASSIGNED RESERVED 60",
 218        [VEC_UNIMPII]   = "UNASSIGNED RESERVED 61",
 219        [VEC_RESV62]    = "UNASSIGNED RESERVED 62",
 220        [VEC_RESV63]    = "UNASSIGNED RESERVED 63",
 221};
 222
 223static const char *space_names[] = {
 224        [0]             = "Space 0",
 225        [USER_DATA]     = "User Data",
 226        [USER_PROGRAM]  = "User Program",
 227#ifndef CONFIG_SUN3
 228        [3]             = "Space 3",
 229#else
 230        [FC_CONTROL]    = "Control",
 231#endif
 232        [4]             = "Space 4",
 233        [SUPER_DATA]    = "Super Data",
 234        [SUPER_PROGRAM] = "Super Program",
 235        [CPU_SPACE]     = "CPU"
 236};
 237
 238void die_if_kernel(char *,struct pt_regs *,int);
 239asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
 240                             unsigned long error_code);
 241int send_fault_sig(struct pt_regs *regs);
 242
 243asmlinkage void trap_c(struct frame *fp);
 244
 245#if defined (CONFIG_M68060)
 246static inline void access_error060 (struct frame *fp)
 247{
 248        unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
 249
 250#ifdef DEBUG
 251        printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
 252#endif
 253
 254        if (fslw & MMU060_BPE) {
 255                /* branch prediction error -> clear branch cache */
 256                __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
 257                                      "orl   #0x00400000,%/d0\n\t"
 258                                      "movec %/d0,%/cacr"
 259                                      : : : "d0" );
 260                /* return if there's no other error */
 261                if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
 262                        return;
 263        }
 264
 265        if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
 266                unsigned long errorcode;
 267                unsigned long addr = fp->un.fmt4.effaddr;
 268
 269                if (fslw & MMU060_MA)
 270                        addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
 271
 272                errorcode = 1;
 273                if (fslw & MMU060_DESC_ERR) {
 274                        __flush_tlb040_one(addr);
 275                        errorcode = 0;
 276                }
 277                if (fslw & MMU060_W)
 278                        errorcode |= 2;
 279#ifdef DEBUG
 280                printk("errorcode = %d\n", errorcode );
 281#endif
 282                do_page_fault(&fp->ptregs, addr, errorcode);
 283        } else if (fslw & (MMU060_SEE)){
 284                /* Software Emulation Error.
 285                 * fault during mem_read/mem_write in ifpsp060/os.S
 286                 */
 287                send_fault_sig(&fp->ptregs);
 288        } else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
 289                   send_fault_sig(&fp->ptregs) > 0) {
 290                printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
 291                printk( "68060 access error, fslw=%lx\n", fslw );
 292                trap_c( fp );
 293        }
 294}
 295#endif /* CONFIG_M68060 */
 296
 297#if defined (CONFIG_M68040)
 298static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
 299{
 300        unsigned long mmusr;
 301        mm_segment_t old_fs = get_fs();
 302
 303        set_fs(MAKE_MM_SEG(wbs));
 304
 305        if (iswrite)
 306                asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
 307        else
 308                asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
 309
 310        asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
 311
 312        set_fs(old_fs);
 313
 314        return mmusr;
 315}
 316
 317static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
 318                                   unsigned long wbd)
 319{
 320        int res = 0;
 321        mm_segment_t old_fs = get_fs();
 322
 323        /* set_fs can not be moved, otherwise put_user() may oops */
 324        set_fs(MAKE_MM_SEG(wbs));
 325
 326        switch (wbs & WBSIZ_040) {
 327        case BA_SIZE_BYTE:
 328                res = put_user(wbd & 0xff, (char __user *)wba);
 329                break;
 330        case BA_SIZE_WORD:
 331                res = put_user(wbd & 0xffff, (short __user *)wba);
 332                break;
 333        case BA_SIZE_LONG:
 334                res = put_user(wbd, (int __user *)wba);
 335                break;
 336        }
 337
 338        /* set_fs can not be moved, otherwise put_user() may oops */
 339        set_fs(old_fs);
 340
 341
 342#ifdef DEBUG
 343        printk("do_040writeback1, res=%d\n",res);
 344#endif
 345
 346        return res;
 347}
 348
 349/* after an exception in a writeback the stack frame corresponding
 350 * to that exception is discarded, set a few bits in the old frame
 351 * to simulate what it should look like
 352 */
 353static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
 354{
 355        fp->un.fmt7.faddr = wba;
 356        fp->un.fmt7.ssw = wbs & 0xff;
 357        if (wba != current->thread.faddr)
 358            fp->un.fmt7.ssw |= MA_040;
 359}
 360
 361static inline void do_040writebacks(struct frame *fp)
 362{
 363        int res = 0;
 364#if 0
 365        if (fp->un.fmt7.wb1s & WBV_040)
 366                printk("access_error040: cannot handle 1st writeback. oops.\n");
 367#endif
 368
 369        if ((fp->un.fmt7.wb2s & WBV_040) &&
 370            !(fp->un.fmt7.wb2s & WBTT_040)) {
 371                res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
 372                                       fp->un.fmt7.wb2d);
 373                if (res)
 374                        fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
 375                else
 376                        fp->un.fmt7.wb2s = 0;
 377        }
 378
 379        /* do the 2nd wb only if the first one was successful (except for a kernel wb) */
 380        if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
 381                res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
 382                                       fp->un.fmt7.wb3d);
 383                if (res)
 384                    {
 385                        fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
 386
 387                        fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
 388                        fp->un.fmt7.wb3s &= (~WBV_040);
 389                        fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
 390                        fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
 391                    }
 392                else
 393                        fp->un.fmt7.wb3s = 0;
 394        }
 395
 396        if (res)
 397                send_fault_sig(&fp->ptregs);
 398}
 399
 400/*
 401 * called from sigreturn(), must ensure userspace code didn't
 402 * manipulate exception frame to circumvent protection, then complete
 403 * pending writebacks
 404 * we just clear TM2 to turn it into a userspace access
 405 */
 406asmlinkage void berr_040cleanup(struct frame *fp)
 407{
 408        fp->un.fmt7.wb2s &= ~4;
 409        fp->un.fmt7.wb3s &= ~4;
 410
 411        do_040writebacks(fp);
 412}
 413
 414static inline void access_error040(struct frame *fp)
 415{
 416        unsigned short ssw = fp->un.fmt7.ssw;
 417        unsigned long mmusr;
 418
 419#ifdef DEBUG
 420        printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
 421        printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
 422                fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
 423        printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
 424                fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
 425                fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
 426#endif
 427
 428        if (ssw & ATC_040) {
 429                unsigned long addr = fp->un.fmt7.faddr;
 430                unsigned long errorcode;
 431
 432                /*
 433                 * The MMU status has to be determined AFTER the address
 434                 * has been corrected if there was a misaligned access (MA).
 435                 */
 436                if (ssw & MA_040)
 437                        addr = (addr + 7) & -8;
 438
 439                /* MMU error, get the MMUSR info for this access */
 440                mmusr = probe040(!(ssw & RW_040), addr, ssw);
 441#ifdef DEBUG
 442                printk("mmusr = %lx\n", mmusr);
 443#endif
 444                errorcode = 1;
 445                if (!(mmusr & MMU_R_040)) {
 446                        /* clear the invalid atc entry */
 447                        __flush_tlb040_one(addr);
 448                        errorcode = 0;
 449                }
 450
 451                /* despite what documentation seems to say, RMW
 452                 * accesses have always both the LK and RW bits set */
 453                if (!(ssw & RW_040) || (ssw & LK_040))
 454                        errorcode |= 2;
 455
 456                if (do_page_fault(&fp->ptregs, addr, errorcode)) {
 457#ifdef DEBUG
 458                        printk("do_page_fault() !=0 \n");
 459#endif
 460                        if (user_mode(&fp->ptregs)){
 461                                /* delay writebacks after signal delivery */
 462#ifdef DEBUG
 463                                printk(".. was usermode - return\n");
 464#endif
 465                                return;
 466                        }
 467                        /* disable writeback into user space from kernel
 468                         * (if do_page_fault didn't fix the mapping,
 469                         * the writeback won't do good)
 470                         */
 471disable_wb:
 472#ifdef DEBUG
 473                        printk(".. disabling wb2\n");
 474#endif
 475                        if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
 476                                fp->un.fmt7.wb2s &= ~WBV_040;
 477                        if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
 478                                fp->un.fmt7.wb3s &= ~WBV_040;
 479                }
 480        } else {
 481                /* In case of a bus error we either kill the process or expect
 482                 * the kernel to catch the fault, which then is also responsible
 483                 * for cleaning up the mess.
 484                 */
 485                current->thread.signo = SIGBUS;
 486                current->thread.faddr = fp->un.fmt7.faddr;
 487                if (send_fault_sig(&fp->ptregs) >= 0)
 488                        printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
 489                               fp->un.fmt7.faddr);
 490                goto disable_wb;
 491        }
 492
 493        do_040writebacks(fp);
 494}
 495#endif /* CONFIG_M68040 */
 496
 497#if defined(CONFIG_SUN3)
 498#include <asm/sun3mmu.h>
 499
 500extern int mmu_emu_handle_fault (unsigned long, int, int);
 501
 502/* sun3 version of bus_error030 */
 503
 504static inline void bus_error030 (struct frame *fp)
 505{
 506        unsigned char buserr_type = sun3_get_buserr ();
 507        unsigned long addr, errorcode;
 508        unsigned short ssw = fp->un.fmtb.ssw;
 509        extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
 510
 511#ifdef DEBUG
 512        if (ssw & (FC | FB))
 513                printk ("Instruction fault at %#010lx\n",
 514                        ssw & FC ?
 515                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
 516                        :
 517                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
 518        if (ssw & DF)
 519                printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
 520                        ssw & RW ? "read" : "write",
 521                        fp->un.fmtb.daddr,
 522                        space_names[ssw & DFC], fp->ptregs.pc);
 523#endif
 524
 525        /*
 526         * Check if this page should be demand-mapped. This needs to go before
 527         * the testing for a bad kernel-space access (demand-mapping applies
 528         * to kernel accesses too).
 529         */
 530
 531        if ((ssw & DF)
 532            && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
 533                if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
 534                        return;
 535        }
 536
 537        /* Check for kernel-space pagefault (BAD). */
 538        if (fp->ptregs.sr & PS_S) {
 539                /* kernel fault must be a data fault to user space */
 540                if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
 541                     // try checking the kernel mappings before surrender
 542                     if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
 543                          return;
 544                        /* instruction fault or kernel data fault! */
 545                        if (ssw & (FC | FB))
 546                                printk ("Instruction fault at %#010lx\n",
 547                                        fp->ptregs.pc);
 548                        if (ssw & DF) {
 549                                /* was this fault incurred testing bus mappings? */
 550                                if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
 551                                   (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
 552                                        send_fault_sig(&fp->ptregs);
 553                                        return;
 554                                }
 555
 556                                printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
 557                                        ssw & RW ? "read" : "write",
 558                                        fp->un.fmtb.daddr,
 559                                        space_names[ssw & DFC], fp->ptregs.pc);
 560                        }
 561                        printk ("BAD KERNEL BUSERR\n");
 562
 563                        die_if_kernel("Oops", &fp->ptregs,0);
 564                        force_sig(SIGKILL, current);
 565                        return;
 566                }
 567        } else {
 568                /* user fault */
 569                if (!(ssw & (FC | FB)) && !(ssw & DF))
 570                        /* not an instruction fault or data fault! BAD */
 571                        panic ("USER BUSERR w/o instruction or data fault");
 572        }
 573
 574
 575        /* First handle the data fault, if any.  */
 576        if (ssw & DF) {
 577                addr = fp->un.fmtb.daddr;
 578
 579// errorcode bit 0:     0 -> no page            1 -> protection fault
 580// errorcode bit 1:     0 -> read fault         1 -> write fault
 581
 582// (buserr_type & SUN3_BUSERR_PROTERR)  -> protection fault
 583// (buserr_type & SUN3_BUSERR_INVALID)  -> invalid page fault
 584
 585                if (buserr_type & SUN3_BUSERR_PROTERR)
 586                        errorcode = 0x01;
 587                else if (buserr_type & SUN3_BUSERR_INVALID)
 588                        errorcode = 0x00;
 589                else {
 590#ifdef DEBUG
 591                        printk ("*** unexpected busfault type=%#04x\n", buserr_type);
 592                        printk ("invalid %s access at %#lx from pc %#lx\n",
 593                                !(ssw & RW) ? "write" : "read", addr,
 594                                fp->ptregs.pc);
 595#endif
 596                        die_if_kernel ("Oops", &fp->ptregs, buserr_type);
 597                        force_sig (SIGBUS, current);
 598                        return;
 599                }
 600
 601//todo: wtf is RM bit? --m
 602                if (!(ssw & RW) || ssw & RM)
 603                        errorcode |= 0x02;
 604
 605                /* Handle page fault. */
 606                do_page_fault (&fp->ptregs, addr, errorcode);
 607
 608                /* Retry the data fault now. */
 609                return;
 610        }
 611
 612        /* Now handle the instruction fault. */
 613
 614        /* Get the fault address. */
 615        if (fp->ptregs.format == 0xA)
 616                addr = fp->ptregs.pc + 4;
 617        else
 618                addr = fp->un.fmtb.baddr;
 619        if (ssw & FC)
 620                addr -= 2;
 621
 622        if (buserr_type & SUN3_BUSERR_INVALID) {
 623                if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
 624                        do_page_fault (&fp->ptregs, addr, 0);
 625       } else {
 626#ifdef DEBUG
 627                printk ("protection fault on insn access (segv).\n");
 628#endif
 629                force_sig (SIGSEGV, current);
 630       }
 631}
 632#else
 633#if defined(CPU_M68020_OR_M68030)
 634static inline void bus_error030 (struct frame *fp)
 635{
 636        volatile unsigned short temp;
 637        unsigned short mmusr;
 638        unsigned long addr, errorcode;
 639        unsigned short ssw = fp->un.fmtb.ssw;
 640#ifdef DEBUG
 641        unsigned long desc;
 642
 643        printk ("pid = %x  ", current->pid);
 644        printk ("SSW=%#06x  ", ssw);
 645
 646        if (ssw & (FC | FB))
 647                printk ("Instruction fault at %#010lx\n",
 648                        ssw & FC ?
 649                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
 650                        :
 651                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
 652        if (ssw & DF)
 653                printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
 654                        ssw & RW ? "read" : "write",
 655                        fp->un.fmtb.daddr,
 656                        space_names[ssw & DFC], fp->ptregs.pc);
 657#endif
 658
 659        /* ++andreas: If a data fault and an instruction fault happen
 660           at the same time map in both pages.  */
 661
 662        /* First handle the data fault, if any.  */
 663        if (ssw & DF) {
 664                addr = fp->un.fmtb.daddr;
 665
 666#ifdef DEBUG
 667                asm volatile ("ptestr %3,%2@,#7,%0\n\t"
 668                              "pmove %%psr,%1@"
 669                              : "=a&" (desc)
 670                              : "a" (&temp), "a" (addr), "d" (ssw));
 671#else
 672                asm volatile ("ptestr %2,%1@,#7\n\t"
 673                              "pmove %%psr,%0@"
 674                              : : "a" (&temp), "a" (addr), "d" (ssw));
 675#endif
 676                mmusr = temp;
 677
 678#ifdef DEBUG
 679                printk("mmusr is %#x for addr %#lx in task %p\n",
 680                       mmusr, addr, current);
 681                printk("descriptor address is %#lx, contents %#lx\n",
 682                       __va(desc), *(unsigned long *)__va(desc));
 683#endif
 684
 685                errorcode = (mmusr & MMU_I) ? 0 : 1;
 686                if (!(ssw & RW) || (ssw & RM))
 687                        errorcode |= 2;
 688
 689                if (mmusr & (MMU_I | MMU_WP)) {
 690                        if (ssw & 4) {
 691                                printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
 692                                       ssw & RW ? "read" : "write",
 693                                       fp->un.fmtb.daddr,
 694                                       space_names[ssw & DFC], fp->ptregs.pc);
 695                                goto buserr;
 696                        }
 697                        /* Don't try to do anything further if an exception was
 698                           handled. */
 699                        if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
 700                                return;
 701                } else if (!(mmusr & MMU_I)) {
 702                        /* probably a 020 cas fault */
 703                        if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
 704                                printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
 705                } else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
 706                        printk("invalid %s access at %#lx from pc %#lx\n",
 707                               !(ssw & RW) ? "write" : "read", addr,
 708                               fp->ptregs.pc);
 709                        die_if_kernel("Oops",&fp->ptregs,mmusr);
 710                        force_sig(SIGSEGV, current);
 711                        return;
 712                } else {
 713#if 0
 714                        static volatile long tlong;
 715#endif
 716
 717                        printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
 718                               !(ssw & RW) ? "write" : "read", addr,
 719                               fp->ptregs.pc, ssw);
 720                        asm volatile ("ptestr #1,%1@,#0\n\t"
 721                                      "pmove %%psr,%0@"
 722                                      : /* no outputs */
 723                                      : "a" (&temp), "a" (addr));
 724                        mmusr = temp;
 725
 726                        printk ("level 0 mmusr is %#x\n", mmusr);
 727#if 0
 728                        asm volatile ("pmove %%tt0,%0@"
 729                                      : /* no outputs */
 730                                      : "a" (&tlong));
 731                        printk("tt0 is %#lx, ", tlong);
 732                        asm volatile ("pmove %%tt1,%0@"
 733                                      : /* no outputs */
 734                                      : "a" (&tlong));
 735                        printk("tt1 is %#lx\n", tlong);
 736#endif
 737#ifdef DEBUG
 738                        printk("Unknown SIGSEGV - 1\n");
 739#endif
 740                        die_if_kernel("Oops",&fp->ptregs,mmusr);
 741                        force_sig(SIGSEGV, current);
 742                        return;
 743                }
 744
 745                /* setup an ATC entry for the access about to be retried */
 746                if (!(ssw & RW) || (ssw & RM))
 747                        asm volatile ("ploadw %1,%0@" : /* no outputs */
 748                                      : "a" (addr), "d" (ssw));
 749                else
 750                        asm volatile ("ploadr %1,%0@" : /* no outputs */
 751                                      : "a" (addr), "d" (ssw));
 752        }
 753
 754        /* Now handle the instruction fault. */
 755
 756        if (!(ssw & (FC|FB)))
 757                return;
 758
 759        if (fp->ptregs.sr & PS_S) {
 760                printk("Instruction fault at %#010lx\n",
 761                        fp->ptregs.pc);
 762        buserr:
 763                printk ("BAD KERNEL BUSERR\n");
 764                die_if_kernel("Oops",&fp->ptregs,0);
 765                force_sig(SIGKILL, current);
 766                return;
 767        }
 768
 769        /* get the fault address */
 770        if (fp->ptregs.format == 10)
 771                addr = fp->ptregs.pc + 4;
 772        else
 773                addr = fp->un.fmtb.baddr;
 774        if (ssw & FC)
 775                addr -= 2;
 776
 777        if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
 778                /* Insn fault on same page as data fault.  But we
 779                   should still create the ATC entry.  */
 780                goto create_atc_entry;
 781
 782#ifdef DEBUG
 783        asm volatile ("ptestr #1,%2@,#7,%0\n\t"
 784                      "pmove %%psr,%1@"
 785                      : "=a&" (desc)
 786                      : "a" (&temp), "a" (addr));
 787#else
 788        asm volatile ("ptestr #1,%1@,#7\n\t"
 789                      "pmove %%psr,%0@"
 790                      : : "a" (&temp), "a" (addr));
 791#endif
 792        mmusr = temp;
 793
 794#ifdef DEBUG
 795        printk ("mmusr is %#x for addr %#lx in task %p\n",
 796                mmusr, addr, current);
 797        printk ("descriptor address is %#lx, contents %#lx\n",
 798                __va(desc), *(unsigned long *)__va(desc));
 799#endif
 800
 801        if (mmusr & MMU_I)
 802                do_page_fault (&fp->ptregs, addr, 0);
 803        else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
 804                printk ("invalid insn access at %#lx from pc %#lx\n",
 805                        addr, fp->ptregs.pc);
 806#ifdef DEBUG
 807                printk("Unknown SIGSEGV - 2\n");
 808#endif
 809                die_if_kernel("Oops",&fp->ptregs,mmusr);
 810                force_sig(SIGSEGV, current);
 811                return;
 812        }
 813
 814create_atc_entry:
 815        /* setup an ATC entry for the access about to be retried */
 816        asm volatile ("ploadr #2,%0@" : /* no outputs */
 817                      : "a" (addr));
 818}
 819#endif /* CPU_M68020_OR_M68030 */
 820#endif /* !CONFIG_SUN3 */
 821
 822asmlinkage void buserr_c(struct frame *fp)
 823{
 824        /* Only set esp0 if coming from user mode */
 825        if (user_mode(&fp->ptregs))
 826                current->thread.esp0 = (unsigned long) fp;
 827
 828#ifdef DEBUG
 829        printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
 830#endif
 831
 832        switch (fp->ptregs.format) {
 833#if defined (CONFIG_M68060)
 834        case 4:                         /* 68060 access error */
 835          access_error060 (fp);
 836          break;
 837#endif
 838#if defined (CONFIG_M68040)
 839        case 0x7:                       /* 68040 access error */
 840          access_error040 (fp);
 841          break;
 842#endif
 843#if defined (CPU_M68020_OR_M68030)
 844        case 0xa:
 845        case 0xb:
 846          bus_error030 (fp);
 847          break;
 848#endif
 849        default:
 850          die_if_kernel("bad frame format",&fp->ptregs,0);
 851#ifdef DEBUG
 852          printk("Unknown SIGSEGV - 4\n");
 853#endif
 854          force_sig(SIGSEGV, current);
 855        }
 856}
 857
 858
 859static int kstack_depth_to_print = 48;
 860
 861void show_trace(unsigned long *stack)
 862{
 863        unsigned long *endstack;
 864        unsigned long addr;
 865        int i;
 866
 867        printk("Call Trace:");
 868        addr = (unsigned long)stack + THREAD_SIZE - 1;
 869        endstack = (unsigned long *)(addr & -THREAD_SIZE);
 870        i = 0;
 871        while (stack + 1 <= endstack) {
 872                addr = *stack++;
 873                /*
 874                 * If the address is either in the text segment of the
 875                 * kernel, or in the region which contains vmalloc'ed
 876                 * memory, it *may* be the address of a calling
 877                 * routine; if so, print it so that someone tracing
 878                 * down the cause of the crash will be able to figure
 879                 * out the call path that was taken.
 880                 */
 881                if (__kernel_text_address(addr)) {
 882#ifndef CONFIG_KALLSYMS
 883                        if (i % 5 == 0)
 884                                printk("\n       ");
 885#endif
 886                        printk(" [<%08lx>] %pS\n", addr, (void *)addr);
 887                        i++;
 888                }
 889        }
 890        printk("\n");
 891}
 892
 893void show_registers(struct pt_regs *regs)
 894{
 895        struct frame *fp = (struct frame *)regs;
 896        mm_segment_t old_fs = get_fs();
 897        u16 c, *cp;
 898        unsigned long addr;
 899        int i;
 900
 901        print_modules();
 902        printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
 903        printk("SR: %04x  SP: %p  a2: %08lx\n", regs->sr, regs, regs->a2);
 904        printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
 905               regs->d0, regs->d1, regs->d2, regs->d3);
 906        printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
 907               regs->d4, regs->d5, regs->a0, regs->a1);
 908
 909        printk("Process %s (pid: %d, task=%p)\n",
 910                current->comm, task_pid_nr(current), current);
 911        addr = (unsigned long)&fp->un;
 912        printk("Frame format=%X ", regs->format);
 913        switch (regs->format) {
 914        case 0x2:
 915                printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
 916                addr += sizeof(fp->un.fmt2);
 917                break;
 918        case 0x3:
 919                printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
 920                addr += sizeof(fp->un.fmt3);
 921                break;
 922        case 0x4:
 923                printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
 924                        : "eff addr=%08lx pc=%08lx\n"),
 925                        fp->un.fmt4.effaddr, fp->un.fmt4.pc);
 926                addr += sizeof(fp->un.fmt4);
 927                break;
 928        case 0x7:
 929                printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
 930                        fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
 931                printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
 932                        fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
 933                printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
 934                        fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
 935                printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
 936                        fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
 937                printk("push data: %08lx %08lx %08lx %08lx\n",
 938                        fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
 939                        fp->un.fmt7.pd3);
 940                addr += sizeof(fp->un.fmt7);
 941                break;
 942        case 0x9:
 943                printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
 944                addr += sizeof(fp->un.fmt9);
 945                break;
 946        case 0xa:
 947                printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
 948                        fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
 949                        fp->un.fmta.daddr, fp->un.fmta.dobuf);
 950                addr += sizeof(fp->un.fmta);
 951                break;
 952        case 0xb:
 953                printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
 954                        fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
 955                        fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
 956                printk("baddr=%08lx dibuf=%08lx ver=%x\n",
 957                        fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
 958                addr += sizeof(fp->un.fmtb);
 959                break;
 960        default:
 961                printk("\n");
 962        }
 963        show_stack(NULL, (unsigned long *)addr);
 964
 965        printk("Code:");
 966        set_fs(KERNEL_DS);
 967        cp = (u16 *)regs->pc;
 968        for (i = -8; i < 16; i++) {
 969                if (get_user(c, cp + i) && i >= 0) {
 970                        printk(" Bad PC value.");
 971                        break;
 972                }
 973                printk(i ? " %04x" : " <%04x>", c);
 974        }
 975        set_fs(old_fs);
 976        printk ("\n");
 977}
 978
 979void show_stack(struct task_struct *task, unsigned long *stack)
 980{
 981        unsigned long *p;
 982        unsigned long *endstack;
 983        int i;
 984
 985        if (!stack) {
 986                if (task)
 987                        stack = (unsigned long *)task->thread.esp0;
 988                else
 989                        stack = (unsigned long *)&stack;
 990        }
 991        endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
 992
 993        printk("Stack from %08lx:", (unsigned long)stack);
 994        p = stack;
 995        for (i = 0; i < kstack_depth_to_print; i++) {
 996                if (p + 1 > endstack)
 997                        break;
 998                if (i % 8 == 0)
 999                        printk("\n       ");
1000                printk(" %08lx", *p++);
1001        }
1002        printk("\n");
1003        show_trace(stack);
1004}
1005
1006/*
1007 * The architecture-independent backtrace generator
1008 */
1009void dump_stack(void)
1010{
1011        unsigned long stack;
1012
1013        show_trace(&stack);
1014}
1015
1016EXPORT_SYMBOL(dump_stack);
1017
1018void bad_super_trap (struct frame *fp)
1019{
1020        console_verbose();
1021        if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
1022                printk ("*** %s ***   FORMAT=%X\n",
1023                        vec_names[(fp->ptregs.vector) >> 2],
1024                        fp->ptregs.format);
1025        else
1026                printk ("*** Exception %d ***   FORMAT=%X\n",
1027                        (fp->ptregs.vector) >> 2,
1028                        fp->ptregs.format);
1029        if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
1030                unsigned short ssw = fp->un.fmtb.ssw;
1031
1032                printk ("SSW=%#06x  ", ssw);
1033
1034                if (ssw & RC)
1035                        printk ("Pipe stage C instruction fault at %#010lx\n",
1036                                (fp->ptregs.format) == 0xA ?
1037                                fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
1038                if (ssw & RB)
1039                        printk ("Pipe stage B instruction fault at %#010lx\n",
1040                                (fp->ptregs.format) == 0xA ?
1041                                fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
1042                if (ssw & DF)
1043                        printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
1044                                ssw & RW ? "read" : "write",
1045                                fp->un.fmtb.daddr, space_names[ssw & DFC],
1046                                fp->ptregs.pc);
1047        }
1048        printk ("Current process id is %d\n", task_pid_nr(current));
1049        die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
1050}
1051
1052asmlinkage void trap_c(struct frame *fp)
1053{
1054        int sig;
1055        siginfo_t info;
1056
1057        if (fp->ptregs.sr & PS_S) {
1058                if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
1059                        /* traced a trapping instruction */
1060                } else
1061                        bad_super_trap(fp);
1062                return;
1063        }
1064
1065        /* send the appropriate signal to the user program */
1066        switch ((fp->ptregs.vector) >> 2) {
1067            case VEC_ADDRERR:
1068                info.si_code = BUS_ADRALN;
1069                sig = SIGBUS;
1070                break;
1071            case VEC_ILLEGAL:
1072            case VEC_LINE10:
1073            case VEC_LINE11:
1074                info.si_code = ILL_ILLOPC;
1075                sig = SIGILL;
1076                break;
1077            case VEC_PRIV:
1078                info.si_code = ILL_PRVOPC;
1079                sig = SIGILL;
1080                break;
1081            case VEC_COPROC:
1082                info.si_code = ILL_COPROC;
1083                sig = SIGILL;
1084                break;
1085            case VEC_TRAP1:
1086            case VEC_TRAP2:
1087            case VEC_TRAP3:
1088            case VEC_TRAP4:
1089            case VEC_TRAP5:
1090            case VEC_TRAP6:
1091            case VEC_TRAP7:
1092            case VEC_TRAP8:
1093            case VEC_TRAP9:
1094            case VEC_TRAP10:
1095            case VEC_TRAP11:
1096            case VEC_TRAP12:
1097            case VEC_TRAP13:
1098            case VEC_TRAP14:
1099                info.si_code = ILL_ILLTRP;
1100                sig = SIGILL;
1101                break;
1102            case VEC_FPBRUC:
1103            case VEC_FPOE:
1104            case VEC_FPNAN:
1105                info.si_code = FPE_FLTINV;
1106                sig = SIGFPE;
1107                break;
1108            case VEC_FPIR:
1109                info.si_code = FPE_FLTRES;
1110                sig = SIGFPE;
1111                break;
1112            case VEC_FPDIVZ:
1113                info.si_code = FPE_FLTDIV;
1114                sig = SIGFPE;
1115                break;
1116            case VEC_FPUNDER:
1117                info.si_code = FPE_FLTUND;
1118                sig = SIGFPE;
1119                break;
1120            case VEC_FPOVER:
1121                info.si_code = FPE_FLTOVF;
1122                sig = SIGFPE;
1123                break;
1124            case VEC_ZERODIV:
1125                info.si_code = FPE_INTDIV;
1126                sig = SIGFPE;
1127                break;
1128            case VEC_CHK:
1129            case VEC_TRAP:
1130                info.si_code = FPE_INTOVF;
1131                sig = SIGFPE;
1132                break;
1133            case VEC_TRACE:             /* ptrace single step */
1134                info.si_code = TRAP_TRACE;
1135                sig = SIGTRAP;
1136                break;
1137            case VEC_TRAP15:            /* breakpoint */
1138                info.si_code = TRAP_BRKPT;
1139                sig = SIGTRAP;
1140                break;
1141            default:
1142                info.si_code = ILL_ILLOPC;
1143                sig = SIGILL;
1144                break;
1145        }
1146        info.si_signo = sig;
1147        info.si_errno = 0;
1148        switch (fp->ptregs.format) {
1149            default:
1150                info.si_addr = (void *) fp->ptregs.pc;
1151                break;
1152            case 2:
1153                info.si_addr = (void *) fp->un.fmt2.iaddr;
1154                break;
1155            case 7:
1156                info.si_addr = (void *) fp->un.fmt7.effaddr;
1157                break;
1158            case 9:
1159                info.si_addr = (void *) fp->un.fmt9.iaddr;
1160                break;
1161            case 10:
1162                info.si_addr = (void *) fp->un.fmta.daddr;
1163                break;
1164            case 11:
1165                info.si_addr = (void *) fp->un.fmtb.daddr;
1166                break;
1167        }
1168        force_sig_info (sig, &info, current);
1169}
1170
1171void die_if_kernel (char *str, struct pt_regs *fp, int nr)
1172{
1173        if (!(fp->sr & PS_S))
1174                return;
1175
1176        console_verbose();
1177        printk("%s: %08x\n",str,nr);
1178        show_registers(fp);
1179        add_taint(TAINT_DIE);
1180        do_exit(SIGSEGV);
1181}
1182
1183/*
1184 * This function is called if an error occur while accessing
1185 * user-space from the fpsp040 code.
1186 */
1187asmlinkage void fpsp040_die(void)
1188{
1189        do_exit(SIGSEGV);
1190}
1191
1192#ifdef CONFIG_M68KFPU_EMU
1193asmlinkage void fpemu_signal(int signal, int code, void *addr)
1194{
1195        siginfo_t info;
1196
1197        info.si_signo = signal;
1198        info.si_errno = 0;
1199        info.si_code = code;
1200        info.si_addr = addr;
1201        force_sig_info(signal, &info, current);
1202}
1203#endif
1204