home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / arch / mips / kernel / traps.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-25  |  9.1 KB  |  380 lines

  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)
  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)
  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)
  176. {
  177.     send_sig(SIGSEGV, current, 1);
  178. }
  179.  
  180. void do_ades(struct pt_regs *regs)
  181. {
  182.     send_sig(SIGSEGV, current, 1);
  183. }
  184.  
  185. void do_ibe(struct pt_regs *regs)
  186. {
  187.     send_sig(SIGSEGV, current, 1);
  188. }
  189.  
  190. void do_dbe(struct pt_regs *regs)
  191. {
  192.     send_sig(SIGSEGV, current, 1);
  193. }
  194.  
  195. void do_ov(struct pt_regs *regs)
  196. {
  197.     send_sig(SIGFPE, current, 1);
  198. }
  199.  
  200. void do_fpe(struct pt_regs *regs)
  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)
  211. {
  212.     send_sig(SIGILL, current, 1);
  213. }
  214.  
  215. void do_tr(struct pt_regs *regs)
  216. {
  217.     send_sig(SIGILL, current, 1);
  218. }
  219.  
  220. void do_ri(struct pt_regs *regs)
  221. {
  222.     send_sig(SIGILL, current, 1);
  223. }
  224.  
  225. void do_cpu(struct pt_regs *regs)
  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)
  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)
  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)
  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)
  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)
  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. }
  380.