root/arch/mips/kernel/traps.c

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

DEFINITIONS

This source file includes following definitions.
  1. console_verbose
  2. die_if_kernel
  3. fix_ade
  4. do_adel
  5. do_ades
  6. do_ibe
  7. do_dbe
  8. do_ov
  9. do_fpe
  10. do_bp
  11. do_tr
  12. do_ri
  13. do_cpu
  14. do_vcei
  15. do_vced
  16. do_watch
  17. do_reserved
  18. trap_init

   1 /*
   2  *  arch/mips/kernel/traps.c
   3  *
   4  * This file is subject to the terms and conditions of the GNU General Public
   5  * License.  See the file "COPYING" in the main directory of this archive
   6  * for more details.
   7  */
   8 
   9 /*
  10  * 'traps.c' handles hardware traps and faults after we have saved some
  11  * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
  12  * to mainly kill the offending process (probably by giving it a signal,
  13  * but possibly by killing it outright if necessary).
  14  *
  15  * FIXME: This is the place for a fpu emulator.
  16  */
  17 #include <linux/head.h>
  18 #include <linux/sched.h>
  19 #include <linux/kernel.h>
  20 #include <linux/signal.h>
  21 #include <linux/string.h>
  22 #include <linux/types.h>
  23 #include <linux/errno.h>
  24 #include <linux/ptrace.h>
  25 #include <linux/timer.h>
  26 #include <linux/mm.h>
  27 
  28 #include <asm/vector.h>
  29 #include <asm/page.h>
  30 #include <asm/pgtable.h>
  31 #include <asm/system.h>
  32 #include <asm/segment.h>
  33 #include <asm/io.h>
  34 #include <asm/mipsregs.h>
  35 #include <asm/bootinfo.h>
  36 
  37 static inline void console_verbose(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39         extern int console_loglevel;
  40         console_loglevel = 15;
  41 }
  42 
  43 /*
  44  * Machine specific interrupt handlers
  45  */
  46 extern asmlinkage void acer_pica_61_handle_int(void);
  47 extern asmlinkage void decstation_handle_int(void);
  48 extern asmlinkage void deskstation_rpc44_handle_int(void);
  49 extern asmlinkage void deskstation_tyne_handle_int(void);
  50 extern asmlinkage void mips_magnum_4000_handle_int(void);
  51 
  52 extern asmlinkage void handle_mod(void);
  53 extern asmlinkage void handle_tlbl(void);
  54 extern asmlinkage void handle_tlbs(void);
  55 extern asmlinkage void handle_adel(void);
  56 extern asmlinkage void handle_ades(void);
  57 extern asmlinkage void handle_ibe(void);
  58 extern asmlinkage void handle_dbe(void);
  59 extern asmlinkage void handle_sys(void);
  60 extern asmlinkage void handle_bp(void);
  61 extern asmlinkage void handle_ri(void);
  62 extern asmlinkage void handle_cpu(void);
  63 extern asmlinkage void handle_ov(void);
  64 extern asmlinkage void handle_tr(void);
  65 extern asmlinkage void handle_vcei(void);
  66 extern asmlinkage void handle_fpe(void);
  67 extern asmlinkage void handle_vced(void);
  68 extern asmlinkage void handle_watch(void);
  69 extern asmlinkage void handle_reserved(void);
  70 
  71 static char *cpu_names[] = CPU_NAMES;
  72 
  73 unsigned long page_colour_mask;
  74 
  75 int kstack_depth_to_print = 24;
  76 
  77 /*
  78  * These constant is for searching for possible module text segments.
  79  * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
  80  */
  81 #define MODULE_RANGE (8*1024*1024)
  82 
  83 void die_if_kernel(char * str, struct pt_regs * regs, long err)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85         int     i;
  86         int     *stack;
  87         u32     *sp, *pc, addr, module_start, module_end;
  88         extern  char start_kernel, _etext;
  89 
  90         if ((regs->cp0_status & (ST0_ERL|ST0_EXL)) == 0)
  91                 return;
  92 
  93         sp = (u32 *)regs->reg29;
  94         pc = (u32 *)regs->cp0_epc;
  95 
  96         console_verbose();
  97         printk("%s: %08lx\n", str, err );
  98 
  99         show_regs(regs);
 100 
 101         /*
 102          * Dump the stack
 103          */
 104         if (STACK_MAGIC != *(u32 *)current->kernel_stack_page)
 105                 printk("Corrupted stack page\n");
 106         printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ",
 107                 current->comm, current->pid, current->kernel_stack_page);
 108         for(i=0;i<5;i++)
 109                 printk("%08x ", *sp++);
 110         stack = (int *) sp;
 111         for(i=0; i < kstack_depth_to_print; i++) {
 112                 if (((u32) stack & (PAGE_SIZE -1)) == 0)
 113                         break;
 114                 if (i && ((i % 8) == 0))
 115                         printk("\n       ");
 116                 printk("%08lx ", get_user(stack++));
 117         }
 118         printk("\nCall Trace: ");
 119         stack = (int *)sp;
 120         i = 1;
 121         module_start = VMALLOC_START;
 122         module_end = module_start + MODULE_RANGE;
 123         while (((u32)stack & (PAGE_SIZE -1)) != 0) {
 124                 addr = get_user(stack++);
 125                 /*
 126                  * If the address is either in the text segment of the
 127                  * kernel, or in the region which contains vmalloc'ed
 128                  * memory, it *may* be the address of a calling
 129                  * routine; if so, print it so that someone tracing
 130                  * down the cause of the crash will be able to figure
 131                  * out the call path that was taken.
 132                  */
 133                 if (((addr >= (u32) &start_kernel) &&
 134                      (addr <= (u32) &_etext)) ||
 135                     ((addr >= module_start) && (addr <= module_end))) {
 136                         if (i && ((i % 8) == 0))
 137                                 printk("\n       ");
 138                         printk("%08x ", addr);
 139                         i++;
 140                 }
 141         }
 142 
 143         printk("\nCode : ");
 144         if ((!verify_area(VERIFY_READ, pc, 5 * sizeof(*pc)) ||
 145              KSEGX(pc) == KSEG0 ||
 146              KSEGX(pc) == KSEG1) &&
 147             (((unsigned long) pc & 3) == 0))
 148         {
 149                 for(i=0;i<5;i++)
 150                         printk("%08x ", *pc++);
 151                 printk("\n");
 152         }
 153         else
 154                 printk("(Bad address in epc)\n");
 155 while(1);
 156         do_exit(SIGSEGV);
 157 }
 158 
 159 static void
 160 fix_ade(struct pt_regs *regs, int write)
     /* [previous][next][first][last][top][bottom][index][help] */
 161 {
 162         printk("Received address error (ade%c)\n", write ? 's' : 'l');
 163         panic("Fixing address errors not implemented yet");
 164 }
 165 
 166 void do_adel(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168         if(current->tss.mflags & MF_FIXADE)
 169         {
 170                 fix_ade(regs, 0);
 171                 return;
 172         }
 173         show_regs(regs);
 174 while(1);
 175         dump_tlb_nonwired();
 176         send_sig(SIGSEGV, current, 1);
 177 }
 178 
 179 void do_ades(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 180 {
 181         unsigned long   pc = regs->cp0_epc;
 182         int     i;
 183 
 184         if(current->tss.mflags & MF_FIXADE)
 185         {
 186                 fix_ade(regs, 1);
 187                 return;
 188         }
 189 while(1);
 190         for(i=0; i<NR_TASKS;i++)
 191                 if(task[i] && task[i]->pid >= 2)
 192                 {
 193                         printk("Process %d\n", task[i]->pid);
 194                         dump_list_process(task[i], pc);
 195                 }
 196         show_regs(regs);
 197         dump_tlb_nonwired();
 198         send_sig(SIGSEGV, current, 1);
 199 }
 200 
 201 /*
 202  * The ibe/dbe exceptions are signaled by onboard hardware and should get
 203  * a board specific handlers to get maximum available information. Bus
 204  * errors are always symptom of hardware malfunction or a kernel error.
 205  *
 206  * FIXME: Linux/68k sends a SIGSEGV for a buserror which seems to be wrong.
 207  * This is certainly wrong. Actually, all hardware errors (ades,adel,ibe,dbe)
 208  * are bus errors and therefor should send a SIGBUS! (Andy)
 209  */
 210 void do_ibe(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212 show_regs(regs);
 213 while(1);
 214         send_sig(SIGBUS, current, 1);
 215 }
 216 
 217 void do_dbe(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 218 {
 219 show_regs(regs);
 220 while(1);
 221         send_sig(SIGBUS, current, 1);
 222 }
 223 
 224 void do_ov(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 225 {
 226 show_regs(regs);
 227 while(1);
 228         send_sig(SIGFPE, current, 1);
 229 }
 230 
 231 void do_fpe(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 232 {
 233 show_regs(regs);
 234 while(1);
 235         send_sig(SIGFPE, current, 1);
 236 }
 237 
 238 void do_bp(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 239 {
 240 show_regs(regs);
 241 while(1);
 242         send_sig(SIGILL, current, 1);
 243 }
 244 
 245 void do_tr(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247 show_regs(regs);
 248 while(1);
 249         send_sig(SIGILL, current, 1);
 250 }
 251 
 252 void do_ri(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 253 {
 254         int     i;
 255 
 256         for(i=0; i<NR_TASKS;i++)
 257                 if(task[i] && task[i]->pid >= 2)
 258                 {
 259                         printk("Process %d\n", task[i]->pid);
 260                         dump_list_process(task[i], 0x7ffff000);
 261                 }
 262         show_regs(regs);
 263 while(1);
 264         send_sig(SIGILL, current, 1);
 265 }
 266 
 267 void do_cpu(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 268 {
 269         unsigned int cpid;
 270 
 271         cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
 272         switch(cpid)
 273         {
 274         case 1:
 275                 regs->cp0_status |= ST0_CU1;
 276                 break;
 277         case 0:
 278                 /*
 279                  * CPU for cp0 can only happen in user mode
 280                  */
 281         case 2:
 282         case 3:
 283                 send_sig(SIGILL, current, 1);
 284                 break;
 285         }
 286 }
 287 
 288 void do_vcei(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 289 {
 290         /*
 291          * Only possible on R4[04]00[SM]C. No handler because
 292          * I don't have such a cpu.
 293          */
 294         panic("Caught VCEI exception - can't handle yet\n");
 295 }
 296 
 297 void do_vced(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 298 {
 299         /*
 300          * Only possible on R4[04]00[SM]C. No handler because
 301          * I don't have such a cpu.
 302          */
 303         panic("Caught VCED exception - can't handle yet\n");
 304 }
 305 
 306 void do_watch(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 307 {
 308         panic("Caught WATCH exception - can't handle yet\n");
 309 }
 310 
 311 void do_reserved(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 312 {
 313         /*
 314          * Game over - no way to handle this if it ever occurs.
 315          * Most probably caused by a new unknown cpu type or
 316          * after another deadly hard/software error.
 317          */
 318         panic("Caught reserved exception - can't handle.\n");
 319 }
 320 
 321 void trap_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 322 {
 323         unsigned long   i;
 324         void watch_set(unsigned long, unsigned long);
 325 
 326         if(boot_info.machtype == MACH_MIPS_MAGNUM_4000)
 327                 EISA_bus = 1;
 328 
 329         /*
 330          * Setup default vectors
 331          */
 332         for (i=0;i<=31;i++)
 333                 set_except_vector(i, handle_reserved);
 334 
 335         /*
 336          * Handling the following exceptions depends mostly of the cpu type
 337          */
 338         switch(boot_info.cputype) {
 339         /*
 340          * The R10000 is in most aspects similar to the R4400.  It however
 341          * should get some special optimizations.
 342          */
 343         case CPU_R10000:
 344                 write_32bit_cp0_register(CP0_FRAMEMASK, 0);
 345                 set_cp0_status(ST0_XX, ST0_XX);
 346                 page_colour_mask = 0x3000;
 347                 panic("CPU too expensive - making holiday in the ANDES!");
 348                 break;
 349         case CPU_R4000MC:
 350         case CPU_R4400MC:
 351         case CPU_R4000SC:
 352         case CPU_R4400SC:
 353                 /*
 354                  * Handlers not implemented yet.  If should ever be used -
 355                  * otherwise it's a bug in the Linux/MIPS kernel, anyway.
 356                  */
 357                 set_except_vector(14, handle_vcei);
 358                 set_except_vector(31, handle_vced);
 359         case CPU_R4000PC:
 360         case CPU_R4400PC:
 361         case CPU_R4200:
 362      /* case CPU_R4300: */
 363                 /*
 364                  * Use watch exception to trap on access to address zero
 365                  */
 366                 set_except_vector(23, handle_watch);
 367                 watch_set(KSEG0, 3);
 368         case CPU_R4600:
 369                 set_except_vector(1, handle_mod);
 370                 set_except_vector(2, handle_tlbl);
 371                 set_except_vector(3, handle_tlbs);
 372                 set_except_vector(4, handle_adel);
 373                 set_except_vector(5, handle_ades);
 374                 /*
 375                  * The following two are signaled by onboard hardware and
 376                  * should get board specific handlers to get maximum
 377                  * available information.
 378                  */
 379                 set_except_vector(6, handle_ibe);
 380                 set_except_vector(7, handle_dbe);
 381 
 382                 set_except_vector(8, handle_sys);
 383                 set_except_vector(9, handle_bp);
 384                 set_except_vector(10, handle_ri);
 385                 set_except_vector(11, handle_cpu);
 386                 set_except_vector(12, handle_ov);
 387                 set_except_vector(13, handle_tr);
 388                 set_except_vector(15, handle_fpe);
 389 
 390                 /*
 391                  * Compute mask for page_colour().  This is based on the
 392                  * size of the data cache.  Does the size of the icache
 393                  * need to be accounted for?
 394                  */
 395                 i = read_32bit_cp0_register(CP0_CONFIG);
 396                 i = (i >> 26) & 7;
 397                 page_colour_mask = 1 << (12 + i);
 398                 break;
 399         case CPU_R2000:
 400         case CPU_R3000:
 401         case CPU_R3000A:
 402         case CPU_R3041:
 403         case CPU_R3051:
 404         case CPU_R3052:
 405         case CPU_R3081:
 406         case CPU_R3081E:
 407         case CPU_R6000:
 408         case CPU_R6000A:
 409         case CPU_R8000:
 410                 printk("Detected unsupported CPU type %s.\n",
 411                         cpu_names[boot_info.cputype]);
 412                 panic("Can't handle CPU\n");
 413                 break;
 414 
 415         case CPU_UNKNOWN:
 416         default:
 417                 panic("Unknown CPU type");
 418         }
 419 
 420         /*
 421          * The interrupt handler mostly depends of the board type.
 422          */
 423         set_except_vector(0, feature->handle_int);
 424 }

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