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

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