root/arch/m68k/kernel/traps.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. trap_init
  2. set_evector
  3. console_verbose
  4. access_error060
  5. probe040
  6. do_040writeback
  7. access_error040
  8. bus_error030
  9. buserr_c
  10. dump_stack
  11. bad_super_trap
  12. trap_c
  13. set_esp0
  14. die_if_kernel

   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  *  68060 fixes by Roman Hodek
   9  *  68060 fixes by Jesper Skov
  10  *
  11  * This file is subject to the terms and conditions of the GNU General Public
  12  * License.  See the file README.legal in the main directory of this archive
  13  * for more details.
  14  */
  15 
  16 /*
  17  * Sets up all exception vectors
  18  */
  19 
  20 #include <linux/config.h>
  21 #include <linux/sched.h>
  22 #include <linux/signal.h>
  23 #include <linux/kernel.h>
  24 #include <linux/mm.h>
  25 #include <linux/types.h>
  26 #include <linux/a.out.h>
  27 #include <linux/user.h>
  28 #include <linux/string.h>
  29 #include <linux/linkage.h>
  30 
  31 #include <asm/system.h>
  32 #include <asm/segment.h>
  33 #include <asm/traps.h>
  34 #include <asm/bootinfo.h>
  35 #include <asm/pgtable.h>
  36 #include <asm/machdep.h>
  37 
  38 /* assembler routines */
  39 asmlinkage void system_call(void);
  40 asmlinkage void buserr(void);
  41 asmlinkage void trap(void);
  42 asmlinkage void inthandler(void);
  43 asmlinkage void nmihandler(void);
  44 
  45 e_vector vectors[256] = {
  46         0, 0, buserr, trap, trap, trap, trap, trap,
  47         trap, trap, trap, trap, trap, trap, trap, trap,
  48         trap, trap, trap, trap, trap, trap, trap, trap,
  49         inthandler, inthandler, inthandler, inthandler,
  50         inthandler, inthandler, inthandler, inthandler,
  51         /* TRAP #0-15 */
  52         system_call, trap, trap, trap, trap, trap, trap, trap,
  53         trap, trap, trap, trap, trap, trap, trap, trap,
  54         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  55 };
  56 
  57 /* nmi handler for the Amiga */
  58 asm(".text\n"
  59     __ALIGN_STR "\n"
  60     SYMBOL_NAME_STR(nmihandler) ": rte");
  61 
  62 void trap_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64         int i;
  65 
  66         /* setup the exception vector table */
  67         __asm__ volatile ("movec %0,%/vbr" : : "r" ((void*)vectors));
  68 
  69         for (i = 48; i < 64; i++)
  70                 vectors[i] = trap;
  71 
  72         for (i = 64; i < 256; i++)
  73                 vectors[i] = inthandler;
  74 
  75         /* if running on an amiga, make the NMI interrupt do nothing */
  76         if (MACH_IS_AMIGA) {
  77                 vectors[VEC_INT7] = nmihandler;
  78         }
  79 
  80 #ifdef CONFIG_FPSP_040
  81         if (m68k_is040or060 == 4) {
  82                 /* set up FPSP entry points */
  83                 asmlinkage void dz_vec(void) asm ("dz");
  84                 asmlinkage void inex_vec(void) asm ("inex");
  85                 asmlinkage void ovfl_vec(void) asm ("ovfl");
  86                 asmlinkage void unfl_vec(void) asm ("unfl");
  87                 asmlinkage void snan_vec(void) asm ("snan");
  88                 asmlinkage void operr_vec(void) asm ("operr");
  89                 asmlinkage void bsun_vec(void) asm ("bsun");
  90                 asmlinkage void fline_vec(void) asm ("fline");
  91                 asmlinkage void unsupp_vec(void) asm ("unsupp");
  92 
  93                 vectors[VEC_FPDIVZ] = dz_vec;
  94                 vectors[VEC_FPIR] = inex_vec;
  95                 vectors[VEC_FPOVER] = ovfl_vec;
  96                 vectors[VEC_FPUNDER] = unfl_vec;
  97                 vectors[VEC_FPNAN] = snan_vec;
  98                 vectors[VEC_FPOE] = operr_vec;
  99                 vectors[VEC_FPBRUC] = bsun_vec;
 100                 vectors[VEC_FPBRUC] = bsun_vec;
 101                 vectors[VEC_LINE11] = fline_vec;
 102                 vectors[VEC_FPUNSUP] = unsupp_vec;
 103         }
 104 #endif
 105 #ifdef CONFIG_IFPSP_060
 106         if (m68k_is040or060 == 6) {
 107           /* set up IFPSP entry points */
 108           asmlinkage void snan_vec(void) asm ("_060_fpsp_snan");
 109           asmlinkage void operr_vec(void) asm ("_060_fpsp_operr");
 110           asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl");
 111           asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl");
 112           asmlinkage void dz_vec(void) asm ("_060_fpsp_dz");
 113           asmlinkage void inex_vec(void) asm ("_060_fpsp_inex");
 114           asmlinkage void fline_vec(void) asm ("_060_fpsp_fline");
 115           asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp");
 116           asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd");
 117   
 118           asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
 119   
 120           vectors[VEC_FPNAN] = snan_vec;
 121           vectors[VEC_FPOE] = operr_vec;
 122           vectors[VEC_FPOVER] = ovfl_vec;
 123           vectors[VEC_FPUNDER] = unfl_vec;
 124           vectors[VEC_FPDIVZ] = dz_vec;
 125           vectors[VEC_FPIR] = inex_vec;
 126           vectors[VEC_LINE11] = fline_vec;
 127           vectors[VEC_FPUNSUP] = unsupp_vec;
 128           vectors[VEC_UNIMPEA] = effadd_vec;
 129   
 130           /* set up ISP entry points */
 131   
 132           vectors[VEC_UNIMPII] = unimp_vec;
 133   
 134         }
 135 #endif
 136 }
 137 
 138 void set_evector(int vecnum, void (*handler)(void))
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140         if (vecnum >= 0 && vecnum <= 256)
 141                 vectors[vecnum] = handler;
 142 }
 143 
 144 
 145 static inline void console_verbose(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147         extern int console_loglevel;
 148         console_loglevel = 15;
 149         mach_debug_init();
 150 }
 151 
 152 char *vec_names[] = {
 153         "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
 154         "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
 155         "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
 156         "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
 157         "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
 158         "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
 159         "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
 160         "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
 161         "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
 162         "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
 163         "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
 164         "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
 165         "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
 166         "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
 167         "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15"
 168         };
 169 
 170 char *space_names[] = {
 171         "Space 0", "User Data", "User Program", "Space 3",
 172         "Space 4", "Super Data", "Super Program", "CPU"
 173         };
 174 
 175 
 176 
 177 extern void die_if_kernel(char *,struct pt_regs *,int);
 178 asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
 179                               unsigned long error_code);
 180 
 181 asmlinkage void trap_c(struct frame *fp);
 182 
 183 static inline void access_error060 (struct frame *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 184 {
 185         unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
 186 
 187 #ifdef DEBUG
 188         printk("fslw=%#lx, fa=%#lx\n", ssw, fp->un.fmt4.effaddr);
 189 #endif
 190 
 191         if (fslw & MMU060_BPE) {
 192                 /* branch prediction error -> clear branch cache */
 193                 __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
 194                                       "orl   #0x00400000,%/d0\n\t"
 195                                       "movec %/d0,%/cacr"
 196                                       : : : "d0" );
 197                 /* return if there's no other error */
 198                 if (!(fslw & MMU060_ERR_BITS))
 199                         return;
 200         }
 201         
 202         if (fslw & (MMU060_DESC_ERR | MMU060_WP)) {
 203                 unsigned long errorcode;
 204                 unsigned long addr = fp->un.fmt4.effaddr;
 205                 errorcode = ((fslw & MMU060_WP) ? 1 : 0) |
 206                                         ((fslw & MMU060_W)  ? 2 : 0);
 207 #ifdef DEBUG
 208                 printk("errorcode = %d\n", errorcode );
 209 #endif
 210                 if (fslw & MMU060_MA)
 211                   addr = PAGE_ALIGN(addr);
 212                 do_page_fault( (struct pt_regs *)fp, addr, errorcode );
 213         }
 214         else {
 215                 printk( "68060 access error, fslw=%lx\n", fslw );
 216                 trap_c( fp );
 217         }
 218 }
 219 
 220 static unsigned long probe040 (int iswrite, int fc, unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 221 {
 222         unsigned long mmusr;
 223         unsigned long fs = get_fs();
 224 
 225         set_fs (fc);
 226 
 227         if (iswrite)
 228                 /* write */
 229                 asm volatile ("movel %1,%/a0\n\t"
 230                               ".word 0xf548\n\t"        /* ptestw (a0) */
 231                               ".long 0x4e7a8805\n\t"    /* movec mmusr,a0 */
 232                               "movel %/a0,%0"
 233                               : "=g" (mmusr)
 234                               : "g" (addr)
 235                               : "a0");
 236         else
 237                 asm volatile ("movel %1,%/a0\n\t"
 238                               ".word 0xf568\n\t"        /* ptestr (a0) */
 239                               ".long 0x4e7a8805\n\t"    /* movec mmusr,a0 */
 240                               "movel %/a0,%0"
 241                               : "=g" (mmusr)
 242                               : "g" (addr)
 243                               : "a0");
 244 
 245 
 246         set_fs (fs);
 247 
 248         return mmusr;
 249 }
 250 
 251 static void do_040writeback (unsigned short ssw,
     /* [previous][next][first][last][top][bottom][index][help] */
 252                              unsigned short wbs,
 253                              unsigned long wba,
 254                              unsigned long wbd,
 255                              struct frame *fp)
 256 {
 257         unsigned long fs = get_fs ();
 258         unsigned long mmusr;
 259         unsigned long errorcode;
 260 
 261         /*
 262          * No special handling for the second writeback anymore.
 263          * It misinterpreted the misaligned status sometimes.
 264          * This way an extra pgae-fault may be caused (Martin Apel).
 265          */
 266 
 267         mmusr = probe040 (1, wbs & WBTM_040,  wba);
 268         errorcode = (mmusr & MMU_R_040) ? 3 : 2;
 269         if (do_page_fault ((struct pt_regs *)fp, wba, errorcode))
 270           /* just return if we can't perform the writeback */
 271           return;
 272 
 273         set_fs (wbs & WBTM_040);
 274         switch (wbs & WBSIZ_040) {
 275             case BA_SIZE_BYTE:
 276                 put_fs_byte (wbd & 0xff, (char *)wba);
 277                 break;
 278             case BA_SIZE_WORD:
 279                 put_fs_word (wbd & 0xffff, (short *)wba);
 280                 break;
 281             case BA_SIZE_LONG:
 282                 put_fs_long (wbd, (int *)wba);
 283                 break;
 284         }
 285         set_fs (fs);
 286 }
 287 
 288 static inline void access_error040 (struct frame *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 289 {
 290         unsigned short ssw = fp->un.fmt7.ssw;
 291         unsigned long mmusr;
 292 
 293 #ifdef DEBUG
 294         printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
 295         printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,  
 296                 fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
 297         printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n", 
 298                 fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
 299                 fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
 300 #endif
 301 
 302 
 303         if (ssw & ATC_040) {
 304                 unsigned long addr = fp->un.fmt7.faddr;
 305                 unsigned long errorcode;
 306 
 307                 /*
 308                  * The MMU status has to be determined AFTER the address
 309                  * has been corrected if there was a misaligned access (MA).
 310                  */
 311                 if (ssw & MA_040)
 312                         addr = PAGE_ALIGN (addr);
 313 
 314                 /* MMU error, get the MMUSR info for this access */
 315                 mmusr = probe040 (!(ssw & RW_040), ssw & TM_040, addr);
 316                 /*
 317 #ifdef DEBUG
 318                 printk("mmusr = %lx\n", mmusr);
 319 #endif
 320 */
 321                 errorcode = ((mmusr & MMU_R_040) ? 1 : 0) |
 322                         ((ssw & RW_040) ? 0 : 2);
 323                 do_page_fault ((struct pt_regs *)fp, addr, errorcode);
 324         } else {
 325                 printk ("68040 access error, ssw=%x\n", ssw);
 326                 trap_c (fp);
 327         }
 328 
 329 #if 0
 330         if (fp->un.fmt7.wb1s & WBV_040)
 331                 printk("access_error040: cannot handle 1st writeback. oops.\n");
 332 #endif
 333 
 334 /*
 335  *  We may have to do a couple of writebacks here.
 336  *
 337  *  MR: we can speed up the thing a little bit and let do_040writeback()
 338  *  not produce another page fault as wb2 corresponds to the address that
 339  *  caused the fault. on write faults no second fault is generated, but
 340  *  on read faults for security reasons (although per definitionem impossible)
 341  */
 342 
 343         if (fp->un.fmt7.wb2s & WBV_040 && (fp->un.fmt7.wb2s &
 344                                            WBTT_040) != BA_TT_MOVE16)
 345                 do_040writeback (ssw,
 346                                  fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
 347                                  fp->un.fmt7.wb2d, fp);
 348 
 349         if (fp->un.fmt7.wb3s & WBV_040)
 350                 do_040writeback (ssw, fp->un.fmt7.wb3s,
 351                                  fp->un.fmt7.wb3a, fp->un.fmt7.wb3d,
 352                                  fp);
 353 }
 354 
 355 static inline void bus_error030 (struct frame *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 356 {
 357         volatile unsigned short temp;
 358         unsigned short mmusr;
 359         unsigned long addr, desc, errorcode;
 360         unsigned short ssw = fp->un.fmtb.ssw;
 361         int user_space_fault = 1;
 362 
 363 #if DEBUG
 364         printk ("pid = %x  ", current->pid);
 365         printk ("SSW=%#06x  ", ssw);
 366 
 367         if (ssw & (FC | FB))
 368                 printk ("Instruction fault at %#010lx\n",
 369                         ssw & FC ?
 370                         fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
 371                         :
 372                         fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
 373         if (ssw & DF)
 374                 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
 375                         ssw & RW ? "read" : "write",
 376                         fp->un.fmtb.daddr,
 377                         space_names[ssw & DFC], fp->ptregs.pc);
 378 #endif
 379 
 380         if (fp->ptregs.sr & PS_S) {
 381                 /* kernel fault must be a data fault to user space */
 382                 if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
 383                         /* instruction fault or kernel data fault! */
 384                         if (ssw & (FC | FB))
 385                                 printk ("Instruction fault at %#010lx\n",
 386                                         fp->ptregs.pc);
 387                         if (ssw & DF) {
 388                                 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
 389                                         ssw & RW ? "read" : "write",
 390                                         fp->un.fmtb.daddr,
 391                                         space_names[ssw & DFC], fp->ptregs.pc);
 392                         }
 393                         printk ("BAD KERNEL BUSERR\n");
 394                         die_if_kernel("Oops",&fp->ptregs,0);
 395                         send_sig(SIGSEGV, current, 1);
 396                         user_space_fault = 0;
 397                 }
 398         } else {
 399                 /* user fault */
 400                 if (!(ssw & (FC | FB)) && !(ssw & DF))
 401                         /* not an instruction fault or data fault! BAD */
 402                         panic ("USER BUSERR w/o instruction or data fault");
 403                 user_space_fault = 1;
 404 #if DEBUG
 405                 printk("User space bus-error\n");
 406 #endif
 407         }
 408 
 409         /* ++andreas: If a data fault and an instruction fault happen
 410            at the same time map in both pages.  */
 411 
 412         /* First handle the data fault, if any.  */
 413         if (ssw & DF)
 414           {
 415             addr = fp->un.fmtb.daddr;
 416 
 417             if (user_space_fault) {
 418                     asm volatile ("ptestr #1,%2@,#7,%0\n\t"
 419                                   "pmove %/psr,%1@"
 420                                   : "=a&" (desc)
 421                                   : "a" (&temp), "a" (addr));
 422                     mmusr = temp;
 423             } else
 424                     mmusr = MMU_I;
 425       
 426 #if DEBUG
 427             printk ("mmusr is %#x for addr %#lx in task %p\n",
 428                     mmusr, addr, current);
 429             printk ("descriptor address is %#lx, contents %#lx\n",
 430                     mm_ptov(desc), *(unsigned long *)mm_ptov(desc));
 431 #endif
 432 
 433             errorcode = (mmusr & MMU_I) ? 0 : 1;
 434               /* if (!(ssw & RW)) updated to 1.2.13pl6 */
 435             if (!(ssw & RW) || ssw & RM)
 436                     errorcode |= 2;
 437 
 438             if (mmusr & MMU_I)
 439                     do_page_fault ((struct pt_regs *)fp, addr, errorcode);
 440 
 441             /* else if ((mmusr & MMU_WP) && !(ssw & RW)) */
 442 
 443             else if ((mmusr & MMU_WP) && (!(ssw & RW) || ssw & RM))
 444                     do_page_fault ((struct pt_regs *)fp, addr, errorcode);
 445             else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
 446                     printk ("invalid %s access at %#lx from pc %#lx\n",
 447                             !(ssw & RW) ? "write" : "read", addr,
 448                             fp->ptregs.pc);
 449                     die_if_kernel("Oops",&fp->ptregs,mmusr);
 450                     send_sig(SIGSEGV, current, 1);
 451                     return;
 452             } else {
 453 #ifdef DEBUG
 454                     static volatile long tlong;
 455 #endif
 456 
 457                     printk ("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
 458                             !(ssw & RW) ? "write" : "read", addr,
 459                             fp->ptregs.pc, ssw);
 460                     asm volatile ("ptestr #1,%1@,#0\n\t"
 461                                   "pmove %/psr,%0@"
 462                                   : /* no outputs */
 463                                   : "a" (&temp), "a" (addr));
 464                     mmusr = temp;
 465 
 466                     printk ("level 0 mmusr is %#x\n", mmusr);
 467 #if 0
 468                     asm volatile ("pmove %/tt0,%0@"
 469                                   : /* no outputs */
 470                                   : "a" (&tlong));
 471                     printk ("tt0 is %#lx, ", tlong);
 472                     asm volatile ("pmove %/tt1,%0@"
 473                                   : /* no outputs */
 474                                   : "a" (&tlong));
 475                     printk ("tt1 is %#lx\n", tlong);
 476 #endif
 477 #if DEBUG
 478                     printk("Unknown SIGSEGV - 1\n");
 479 #endif
 480                     die_if_kernel("Oops",&fp->ptregs,mmusr);
 481                     send_sig(SIGSEGV, current, 1);
 482                     return;
 483             }
 484 
 485             /* setup an ATC entry for the access about to be retried */
 486             if (!(ssw & RW))
 487                     asm volatile ("ploadw #1,%0@" : /* no outputs */
 488                                   : "a" (addr));
 489             else
 490                     asm volatile ("ploadr #1,%0@" : /* no outputs */
 491                                   : "a" (addr));
 492 
 493             /* If this was a data fault due to an invalid page and a
 494                prefetch is pending on the same page, simulate it (but
 495                only if the page is now valid).  Otherwise we'll get an
 496                weird insn access.  */
 497             if ((ssw & RB) && (mmusr & MMU_I))
 498               {
 499                 unsigned long iaddr;
 500 
 501                 if ((fp->ptregs.format) == 0xB)
 502                   iaddr = fp->un.fmtb.baddr;
 503                 else
 504                   iaddr = fp->ptregs.pc + 4;
 505                 if (((addr ^ iaddr) & PAGE_MASK) == 0)
 506                   {
 507                     /* We only need to check the ATC as the entry has
 508                        already been set up above.  */
 509                     asm volatile ("ptestr #1,%1@,#0\n\t"
 510                                   "pmove %/psr,%0@"
 511                                   : : "a" (&temp), "a" (iaddr));
 512                     mmusr = temp;
 513 #ifdef DEBUG
 514                     printk ("prefetch iaddr=%#lx ssw=%#x mmusr=%#x\n",
 515                             iaddr, ssw, mmusr);
 516 #endif
 517                     if (!(mmusr & MMU_I))
 518                       {
 519                         unsigned short insn;
 520                         asm volatile ("movesw %1@,%0"
 521                                       : "=r" (insn)
 522                                       : "a" (iaddr));
 523                         fp->un.fmtb.isb = insn;
 524                         fp->un.fmtb.ssw &= ~RB;
 525                       }
 526                   }
 527               }
 528           }
 529 
 530         /* Now handle the instruction fault. */
 531 
 532         /* get the fault address */
 533         if ((fp->ptregs.format) == 0xA )
 534                 if (ssw & FC)
 535                         addr = fp->ptregs.pc + 2;
 536                 else if (ssw & FB)
 537                         addr = fp->ptregs.pc + 4;
 538                 else
 539                         return;
 540         else
 541                 if (ssw & FC)
 542                         addr = fp->un.fmtb.baddr - 2;
 543                 else if (ssw & FB)
 544                         addr = fp->un.fmtb.baddr;
 545                 else
 546                         return;
 547 
 548         if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
 549                 /* Insn fault on same page as data fault */
 550                 return;
 551 
 552         if (user_space_fault) {
 553                 asm volatile ("ptestr #1,%2@,#7,%0\n\t"
 554                               "pmove %/psr,%1@"
 555                               : "=a&" (desc)
 556                               : "a" (&temp), "a" (addr));
 557                 mmusr = temp;
 558         } else
 559                 mmusr = MMU_I;
 560       
 561 #ifdef DEBUG
 562         printk ("mmusr is %#x for addr %#lx in task %p\n",
 563                 mmusr, addr, current);
 564         printk ("descriptor address is %#lx, contents %#lx\n",
 565                 mm_ptov(desc), *(unsigned long *)mm_ptov(desc));
 566 #endif
 567 
 568         errorcode = (mmusr & MMU_I) ? 0 : 1;
 569 
 570         if (mmusr & MMU_I)
 571                 do_page_fault ((struct pt_regs *)fp, addr, errorcode);
 572         else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
 573                 printk ("invalid insn access at %#lx from pc %#lx\n",
 574                         addr, fp->ptregs.pc);
 575 #if DEBUG
 576                 printk("Unknown SIGSEGV - 2\n");
 577 #endif
 578                 die_if_kernel("Oops",&fp->ptregs,mmusr);
 579                 send_sig(SIGSEGV, current, 1);
 580                 return;
 581         } else {
 582 #ifdef DEBUG
 583                 static volatile long tlong;
 584 #endif
 585 
 586                 printk ("weird insn access at %#lx from pc %#lx (ssw is %#x)\n",
 587                         addr, fp->ptregs.pc, ssw);
 588                 asm volatile ("ptestr #1,%1@,#0\n\t"
 589                               "pmove %/psr,%0@"
 590                               : /* no outputs */
 591                               : "a" (&temp), "a" (addr));
 592                 mmusr = temp;
 593                       
 594                 printk ("level 0 mmusr is %#x\n", mmusr);
 595 #ifdef DEBUG
 596                 if (boot_info.cputype & CPU_68030) {
 597                         asm volatile ("pmove %/tt0,%0@"
 598                                       : /* no outputs */
 599                                       : "a" (&tlong));
 600                         printk ("tt0 is %#lx, ", tlong);
 601                         asm volatile ("pmove %/tt1,%0@"
 602                                       : /* no outputs */
 603                                       : "a" (&tlong));
 604                         printk ("tt1 is %#lx\n", tlong);
 605                 }
 606 
 607 #endif
 608 #if DEBUG
 609                 printk("Unknown SIGSEGV - 3\n");
 610 #endif
 611                 die_if_kernel("Oops",&fp->ptregs,mmusr);
 612                 send_sig(SIGSEGV, current, 1);
 613                 return;
 614         }
 615 
 616         /* setup an ATC entry for the access about to be retried */
 617         asm volatile ("ploadr #1,%0@" : /* no outputs */
 618                       : "a" (addr));
 619 }
 620 
 621 asmlinkage void buserr_c(struct frame *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 622 {
 623         /* Only set esp0 if coming from user mode */
 624         if (user_mode(&fp->ptregs))
 625                 current->tss.esp0 = (unsigned long) fp;
 626 
 627 #if DEBUG
 628         printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
 629 #endif
 630 
 631         switch (fp->ptregs.format) {
 632         case 4:                         /* 68060 access error */
 633           access_error060 (fp);
 634           break;
 635         case 0x7:                       /* 68040 access error */
 636           access_error040 (fp);
 637           break;
 638         case 0xa:
 639         case 0xb:
 640           bus_error030 (fp);
 641           break;
 642         default:
 643           die_if_kernel("bad frame format",&fp->ptregs,0);
 644 #if DEBUG
 645           printk("Unknown SIGSEGV - 4\n");
 646 #endif
 647           send_sig(SIGSEGV, current, 1);
 648         }
 649 }
 650 
 651 
 652 int kstack_depth_to_print = 48;
 653 
 654 /* MODULE_RANGE is a guess of how much space is likely to be
 655    vmalloced.  */
 656 #define MODULE_RANGE (8*1024*1024)
 657 
 658 static void dump_stack(struct frame *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 659 {
 660         unsigned long *stack, *endstack, addr, module_start, module_end;
 661         extern char _start, _etext;
 662         int i;
 663 
 664         addr = (unsigned long)&fp->un;
 665         printk("Frame format=%X ", fp->ptregs.format);
 666         switch (fp->ptregs.format) {
 667         case 0x2:
 668             printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
 669             addr += sizeof(fp->un.fmt2);
 670             break;
 671         case 0x3:
 672             printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
 673             addr += sizeof(fp->un.fmt3);
 674             break;
 675         case 0x4:
 676             printk((m68k_is040or060 == 6 ? "fault addr=%08lx fslw=%08lx\n"
 677                     : "eff addr=%08lx pc=%08lx\n"),
 678                    fp->un.fmt4.effaddr, fp->un.fmt4.pc);
 679             addr += sizeof(fp->un.fmt4);
 680             break;
 681         case 0x7:
 682             printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
 683                    fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
 684             printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
 685                    fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
 686             printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
 687                    fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
 688             printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
 689                    fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
 690             printk("push data: %08lx %08lx %08lx %08lx\n",
 691                    fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
 692                    fp->un.fmt7.pd3);
 693             addr += sizeof(fp->un.fmt7);
 694             break;
 695         case 0x9:
 696             printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
 697             addr += sizeof(fp->un.fmt9);
 698             break;
 699         case 0xa:
 700             printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
 701                    fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
 702                    fp->un.fmta.daddr, fp->un.fmta.dobuf);
 703             addr += sizeof(fp->un.fmta);
 704             break;
 705         case 0xb:
 706             printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
 707                    fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
 708                    fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
 709             printk("baddr=%08lx dibuf=%08lx ver=%x\n",
 710                    fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
 711             addr += sizeof(fp->un.fmtb);
 712             break;
 713         default:
 714             printk("\n");
 715         }
 716 
 717         stack = (unsigned long *)addr;
 718         endstack = (unsigned long *)PAGE_ALIGN(addr);
 719 
 720         printk("Stack from %08lx:\n       ", (unsigned long)stack);
 721         for (i = 0; i < kstack_depth_to_print; i++) {
 722                 if (stack + 1 > endstack)
 723                         break;
 724                 if (i && ((i % 8) == 0))
 725                         printk("\n       ");
 726                 printk("%08lx ", *stack++);
 727         }
 728 
 729         printk ("\nCall Trace: ");
 730         stack = (unsigned long *) addr;
 731         i = 1;
 732         module_start = VMALLOC_START;
 733         module_end = module_start + MODULE_RANGE;
 734         while (stack + 1 <= endstack) {
 735                 addr = *stack++;
 736                 /*
 737                  * If the address is either in the text segment of the
 738                  * kernel, or in the region which contains vmalloc'ed
 739                  * memory, it *may* be the address of a calling
 740                  * routine; if so, print it so that someone tracing
 741                  * down the cause of the crash will be able to figure
 742                  * out the call path that was taken.
 743                  */
 744                 if (((addr >= (unsigned long) &_start) &&
 745                      (addr <= (unsigned long) &_etext)) ||
 746                     ((addr >= module_start) && (addr <= module_end))) {
 747                         if (i && ((i % 8) == 0))
 748                                 printk("\n       ");
 749                         printk("[<%08lx>] ", addr);
 750                         i++;
 751                 }
 752         }
 753         printk("\nCode: ");
 754         for (i = 0; i < 10; i++)
 755                 printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
 756         printk ("\n");
 757 }
 758 
 759 void bad_super_trap (struct frame *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 760 {
 761         console_verbose();
 762         if ((fp->ptregs.vector) < 48*4)
 763                 printk ("*** %s ***   FORMAT=%X\n",
 764                         vec_names[(fp->ptregs.vector) >> 2],
 765                         fp->ptregs.format);
 766         else
 767                 printk ("*** Exception %d ***   FORMAT=%X\n",
 768                         (fp->ptregs.vector) >> 2, 
 769                         fp->ptregs.format);
 770         if (((fp->ptregs.vector) >> 2) == VEC_ADDRERR
 771             && !m68k_is040or060) {
 772                 unsigned short ssw = fp->un.fmtb.ssw;
 773 
 774                 printk ("SSW=%#06x  ", ssw);
 775 
 776                 if (ssw & RC)
 777                         printk ("Pipe stage C instruction fault at %#010lx\n",
 778                                 (fp->ptregs.format) == 0xA ?
 779                                 fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
 780                 if (ssw & RB)
 781                         printk ("Pipe stage B instruction fault at %#010lx\n",
 782                                 (fp->ptregs.format) == 0xA ?
 783                                 fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
 784                 if (ssw & DF)
 785                         printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
 786                                 ssw & RW ? "read" : "write",
 787                                 fp->un.fmtb.daddr, space_names[ssw & DFC],
 788                                 fp->ptregs.pc);
 789         }
 790         printk ("Current process id is %d\n", current->pid);
 791         die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
 792 }
 793 
 794 asmlinkage void trap_c(struct frame *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 795 {
 796         int sig;
 797 
 798         if ((fp->ptregs.sr & PS_S)
 799             && ((fp->ptregs.vector) >> 2) == VEC_TRACE
 800             && !(fp->ptregs.sr & PS_T)) {
 801                 /* traced a trapping instruction */
 802                 unsigned char *lp = ((unsigned char *)&fp->un.fmt2) + 4;
 803                 current->flags |= PF_DTRACE;
 804                 /* clear the trace bit */
 805                 (*(unsigned short *)lp) &= ~PS_T;
 806                 return;
 807         } else if (fp->ptregs.sr & PS_S) {
 808                 bad_super_trap(fp);
 809                 return;
 810         }
 811 
 812         /* send the appropriate signal to the user program */
 813         switch ((fp->ptregs.vector) >> 2) {
 814             case VEC_ADDRERR:
 815                 sig = SIGBUS;
 816                 break;
 817             case VEC_BUSERR:
 818                 sig = SIGSEGV;
 819                 break;
 820             case VEC_ILLEGAL:
 821             case VEC_PRIV:
 822             case VEC_LINE10:
 823             case VEC_LINE11:
 824             case VEC_COPROC:
 825             case VEC_TRAP1:
 826             case VEC_TRAP2:
 827             case VEC_TRAP3:
 828             case VEC_TRAP4:
 829             case VEC_TRAP5:
 830             case VEC_TRAP6:
 831             case VEC_TRAP7:
 832             case VEC_TRAP8:
 833             case VEC_TRAP9:
 834             case VEC_TRAP10:
 835             case VEC_TRAP11:
 836             case VEC_TRAP12:
 837             case VEC_TRAP13:
 838             case VEC_TRAP14:
 839                 sig = SIGILL;
 840                 break;
 841             case VEC_FPBRUC:
 842             case VEC_FPIR:
 843             case VEC_FPDIVZ:
 844             case VEC_FPUNDER:
 845             case VEC_FPOE:
 846             case VEC_FPOVER:
 847             case VEC_FPNAN:
 848                 {
 849                   unsigned char fstate[216];
 850 
 851                   __asm__ __volatile__ ("fsave %0@" : : "a" (fstate) : "memory");
 852                   /* Set the exception pending bit in the 68882 idle frame */
 853                   if (*(unsigned short *) fstate == 0x1f38)
 854                     {
 855                       fstate[fstate[1]] |= 1 << 3;
 856                       __asm__ __volatile__ ("frestore %0@" : : "a" (fstate));
 857                     }
 858                 }
 859                 /* fall through */
 860             case VEC_ZERODIV:
 861             case VEC_TRAP:
 862                 sig = SIGFPE;
 863                 break;
 864             case VEC_TRACE:             /* ptrace single step */
 865                 fp->ptregs.sr &= ~PS_T;
 866             case VEC_TRAP15:            /* breakpoint */
 867                 sig = SIGTRAP;
 868                 break;
 869             default:
 870                 sig = SIGILL;
 871                 break;
 872         }
 873 
 874         send_sig (sig, current, 1);
 875 }
 876 
 877 asmlinkage void set_esp0 (unsigned long ssp)
     /* [previous][next][first][last][top][bottom][index][help] */
 878 {
 879   current->tss.esp0 = ssp;
 880 }
 881 
 882 void die_if_kernel (char *str, struct pt_regs *fp, int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 883 {
 884         if (!(fp->sr & PS_S))
 885                 return;
 886 
 887         console_verbose();
 888         printk("%s: %08x\n",str,nr);
 889         printk("PC: %08lx\nSR: %04x  SP: %p\n", fp->pc, fp->sr, fp);
 890         printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
 891                fp->d0, fp->d1, fp->d2, fp->d3);
 892         printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
 893                fp->d4, fp->d5, fp->a0, fp->a1);
 894 
 895         if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page)
 896                 printk("Corrupted stack page\n");
 897         printk("Process %s (pid: %d, stackpage=%08lx)\n",
 898                 current->comm, current->pid, current->kernel_stack_page);
 899         dump_stack((struct frame *)fp);
 900         do_exit(SIGSEGV);
 901 }

/* [previous][next][first][last][top][bottom][index][help] */