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. do_adel
  4. do_ades
  5. do_ibe
  6. do_dbe
  7. do_ov
  8. do_fpe
  9. do_bp
  10. do_tr
  11. do_ri
  12. do_cpu
  13. do_vcei
  14. do_vced
  15. do_watch
  16. do_reserved
  17. trap_init

   1 /*
   2  *  arch/mips/kernel/traps.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  * 'traps.c' handles hardware traps and faults after we have saved some
   9  * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
  10  * to mainly kill the offending process (probably by giving it a signal,
  11  * but possibly by killing it outright if necessary).
  12  */
  13 #include <linux/head.h>
  14 #include <linux/sched.h>
  15 #include <linux/kernel.h>
  16 #include <linux/signal.h>
  17 #include <linux/string.h>
  18 #include <linux/errno.h>
  19 #include <linux/ptrace.h>
  20 #include <linux/config.h>
  21 #include <linux/timer.h>
  22 
  23 #include <asm/system.h>
  24 #include <asm/segment.h>
  25 #include <asm/io.h>
  26 #include <asm/mipsregs.h>
  27 #include <asm/bootinfo.h>
  28 
  29 static inline void console_verbose(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31         extern int console_loglevel;
  32         console_loglevel = 15;
  33 }
  34 
  35 #define get_seg_byte(seg,addr) ({ \
  36 register unsigned char __res; \
  37 int unsigned long save; \
  38 save = segment_fs; \
  39 __res = get_user_byte(addr); \
  40 segment_fs = save; \
  41 __res;})
  42 
  43 #define get_seg_long(seg,addr) ({ \
  44 register unsigned long __res; \
  45 int unsigned long save; \
  46 save = segment_fs; \
  47 __res = get_user_word(addr); \
  48 segment_fs = save; \
  49 __res;})
  50 
  51 extern asmlinkage void handle_int(void);
  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 char *cpu_names[] = CPU_NAMES;
  72 
  73 int kstack_depth_to_print = 24;
  74 
  75 /*
  76  * These constants are for searching for possible module text
  77  * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
  78  * a guess of how much space is likely to be vmalloced.
  79  */
  80 #define VMALLOC_OFFSET (8*1024*1024)
  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         unsigned long *sp, *pc;
  87         unsigned long *stack, 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 = (unsigned long *)regs->reg29;
  94         pc = (unsigned long *)regs->cp0_epc;
  95 
  96         console_verbose();
  97         printk("%s: %08lx\n", str, err );
  98 
  99         /*
 100          * Saved main processor registers
 101          */
 102         printk("at   : %08lx\n", regs->reg1);
 103         printk("v0   : %08lx %08lx\n", regs->reg2, regs->reg3);
 104         printk("a0   : %08lx %08lx %08lx %08lx\n",
 105                regs->reg4, regs->reg5, regs->reg6, regs->reg7);
 106         printk("t0   : %08lx %08lx %08lx %08lx %08lx\n",
 107                regs->reg8, regs->reg9, regs->reg10, regs->reg11, regs->reg12);
 108         printk("t5   : %08lx %08lx %08lx %08lx %08lx\n",
 109                regs->reg13, regs->reg14, regs->reg15, regs->reg24, regs->reg25);
 110         printk("s0   : %08lx %08lx %08lx %08lx\n",
 111                regs->reg16, regs->reg17, regs->reg18, regs->reg19);
 112         printk("s4   : %08lx %08lx %08lx %08lx\n",
 113                regs->reg20, regs->reg21, regs->reg22, regs->reg23);
 114         printk("gp   : %08lx\n", regs->reg28);
 115         printk("sp   : %08lx\n", regs->reg29);
 116         printk("fp/s8: %08lx\n", regs->reg30);
 117         printk("ra   : %08lx\n", regs->reg31);
 118 
 119         /*
 120          * Saved cp0 registers
 121          */
 122         printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
 123                regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
 124 
 125         /*
 126          * Some goodies...
 127          */
 128         printk("Int  : %ld\n", regs->interrupt);
 129 
 130         /*
 131          * Dump the stack
 132          */
 133         if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page)
 134                 printk("Corrupted stack page\n");
 135         printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ",
 136                 current->comm, current->pid, 0xffff & i,
 137                 current->kernel_stack_page);
 138         for(i=0;i<5;i++)
 139                 printk("%08lx ", *sp++);
 140         stack = (unsigned long *) sp;
 141         for(i=0; i < kstack_depth_to_print; i++) {
 142                 if (((long) stack & 4095) == 0)
 143                         break;
 144                 if (i && ((i % 8) == 0))
 145                         printk("\n       ");
 146                 printk("%08lx ", get_seg_long(ss,stack++));
 147         }
 148         printk("\nCall Trace: ");
 149         stack = (unsigned long *) sp;
 150         i = 1;
 151         module_start = ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
 152         module_end = module_start + MODULE_RANGE;
 153         while (((long) stack & 4095) != 0) {
 154                 addr = get_seg_long(ss, stack++);
 155                 /*
 156                  * If the address is either in the text segment of the
 157                  * kernel, or in the region which contains vmalloc'ed
 158                  * memory, it *may* be the address of a calling
 159                  * routine; if so, print it so that someone tracing
 160                  * down the cause of the crash will be able to figure
 161                  * out the call path that was taken.
 162                  */
 163                 if (((addr >= (unsigned long) &start_kernel) &&
 164                      (addr <= (unsigned long) &etext)) ||
 165                     ((addr >= module_start) && (addr <= module_end))) {
 166                         if (i && ((i % 8) == 0))
 167                                 printk("\n       ");
 168                         printk("%08lx ", addr);
 169                         i++;
 170                 }
 171         }
 172 
 173         printk("\nCode : ");
 174         for(i=0;i<5;i++)
 175                 printk("%08lx ", *pc++);
 176         printk("\n");
 177         do_exit(SIGSEGV);
 178 }
 179 
 180 void do_adel(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 181 {
 182         send_sig(SIGSEGV, current, 1);
 183 }
 184 
 185 void do_ades(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187         send_sig(SIGSEGV, current, 1);
 188 }
 189 
 190 void do_ibe(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192         send_sig(SIGSEGV, current, 1);
 193 }
 194 
 195 void do_dbe(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197         send_sig(SIGSEGV, current, 1);
 198 }
 199 
 200 void do_ov(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202         send_sig(SIGFPE, current, 1);
 203 }
 204 
 205 void do_fpe(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 206 {
 207         /*
 208          * FIXME: This is the place for a fpu emulator. Not written
 209          * yet and the demand seems to be quite low.
 210          */
 211         printk("Caught FPE exception at %lx.\n", regs->cp0_epc);
 212         send_sig(SIGFPE, current, 1);
 213 }
 214 
 215 void do_bp(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 216 {
 217         send_sig(SIGILL, current, 1);
 218 }
 219 
 220 void do_tr(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 221 {
 222         send_sig(SIGILL, current, 1);
 223 }
 224 
 225 void do_ri(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 226 {
 227         send_sig(SIGILL, current, 1);
 228 }
 229 
 230 void do_cpu(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232         unsigned long pc;
 233         unsigned int insn;
 234 
 235         /*
 236          * Check whether this was a cp1 instruction
 237          */
 238         pc = regs->cp0_epc;
 239         if (regs->cp0_cause & (1<<31))
 240                 pc += 4;
 241         insn = *(unsigned int *)pc;
 242         insn &= 0xfc000000;
 243         switch(insn) {
 244                 case 0x44000000:
 245                 case 0xc4000000:
 246                 case 0xe4000000:
 247                         printk("CP1 instruction - enabling cp1.\n");
 248                         regs->cp0_status |= ST0_CU1;
 249                         /*
 250                          * No need to handle branch delay slots
 251                          */
 252                         break;
 253                 default:
 254                         /*
 255                          * This wasn't a cp1 instruction and therefore illegal.
 256                          * Default is to kill the process.
 257                          */
 258                         send_sig(SIGILL, current, 1);
 259                 }
 260 }
 261 
 262 void do_vcei(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 263 {
 264         /*
 265          * Only possible on R4[04]00[SM]C. No handler because
 266          * I don't have such a cpu.
 267          */
 268         panic("Caught VCEI exception - can't handle yet\n");
 269 }
 270 
 271 void do_vced(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 272 {
 273         /*
 274          * Only possible on R4[04]00[SM]C. No handler because
 275          * I don't have such a cpu.
 276          */
 277         panic("Caught VCED exception - can't handle yet\n");
 278 }
 279 
 280 void do_watch(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 281 {
 282         /*
 283          * Only possible on R4[04]00. No way to handle this because
 284          * I don't have such a cpu.
 285          */
 286         panic("Caught WATCH exception - can't handle yet\n");
 287 }
 288 
 289 void do_reserved(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 290 {
 291         /*
 292          * Game over - no way to handle this if it ever occurs.
 293          * Most probably caused by a new unknown cpu type or a
 294          * after another deadly hard/software error.
 295          */
 296         panic("Caught reserved exception - can't handle.\n");
 297 }
 298 
 299 void trap_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 300 {
 301         int     i;
 302 
 303         /*
 304          * FIXME: Mips Magnum R4000 has an EISA bus!
 305          */
 306         EISA_bus = 0;
 307 
 308         /*
 309          * Setup default vectors
 310          */
 311         for (i=0;i<=31;i++)
 312                 set_except_vector(i, handle_reserved);
 313 
 314         /*
 315          * Handling the following exceptions depends mostly of the cpu type
 316          */
 317         switch(boot_info.cputype) {
 318         case CPU_R4000MC:
 319         case CPU_R4400MC:
 320         case CPU_R4000SC:
 321         case CPU_R4400SC:
 322                 /*
 323                  * Handlers not implemented yet
 324                  */
 325                 set_except_vector(14, handle_vcei);
 326                 set_except_vector(31, handle_vced);
 327         case CPU_R4000PC:
 328         case CPU_R4400PC:
 329                 /*
 330                  * Handler not implemented yet
 331                  */
 332                 set_except_vector(23, handle_watch);
 333         case CPU_R4200:
 334         case CPU_R4600:
 335                 set_except_vector(1, handle_mod);
 336                 set_except_vector(2, handle_tlbl);
 337                 set_except_vector(3, handle_tlbs);
 338                 set_except_vector(4, handle_adel);
 339                 set_except_vector(5, handle_ades);
 340                 set_except_vector(6, handle_ibe);
 341                 set_except_vector(7, handle_dbe);
 342                 set_except_vector(8, handle_sys);
 343                 set_except_vector(9, handle_bp);
 344                 set_except_vector(10, handle_ri);
 345                 set_except_vector(11, handle_cpu);
 346                 set_except_vector(12, handle_ov);
 347                 set_except_vector(13, handle_tr);
 348                 set_except_vector(15, handle_fpe);
 349                 break;
 350         case CPU_R2000:
 351         case CPU_R3000:
 352         case CPU_R3000A:
 353         case CPU_R3041:
 354         case CPU_R3051:
 355         case CPU_R3052:
 356         case CPU_R3081:
 357         case CPU_R3081E:
 358         case CPU_R6000:
 359         case CPU_R6000A:
 360         case CPU_R8000:
 361         case CPU_R10000:
 362                 printk("Detected unsupported CPU type %s.\n",
 363                        cpu_names[boot_info.cputype]);
 364                 panic("Can't handle CPU\n");
 365                 break;
 366         case CPU_UNKNOWN:
 367         default:
 368                 panic("Unknown type of CPU");
 369                 }
 370 
 371         /*
 372          * The interrupt handler depends of both type of the board and cpu
 373          */
 374         switch(boot_info.machtype) {
 375         case MACH_DESKSTATION_TYNE:
 376                 set_except_vector(0, handle_int);
 377                 }
 378 }

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