traps.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:23k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (C) 1994 - 1999, 2000, 01 Ralf Baechle
  7.  * Modified for R3000 by Paul M. Antoine, 1995, 1996
  8.  * Complete output from die() by Ulf Carlsson, 1998
  9.  * Copyright (C) 1999 Silicon Graphics, Inc.
  10.  *
  11.  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  12.  * Copyright (C) 2000, 01 MIPS Technologies, Inc.
  13.  */
  14. #include <linux/config.h>
  15. #include <linux/init.h>
  16. #include <linux/mm.h>
  17. #include <linux/module.h>
  18. #include <linux/sched.h>
  19. #include <linux/smp.h>
  20. #include <linux/smp_lock.h>
  21. #include <linux/spinlock.h>
  22. #include <asm/bootinfo.h>
  23. #include <asm/branch.h>
  24. #include <asm/cpu.h>
  25. #include <asm/cachectl.h>
  26. #include <asm/inst.h>
  27. #include <asm/jazz.h>
  28. #include <asm/module.h>
  29. #include <asm/pgtable.h>
  30. #include <asm/io.h>
  31. #include <asm/siginfo.h>
  32. #include <asm/watch.h>
  33. #include <asm/system.h>
  34. #include <asm/uaccess.h>
  35. #include <asm/mmu_context.h>
  36. /*
  37.  * Machine specific interrupt handlers
  38.  */
  39. extern asmlinkage void acer_pica_61_handle_int(void);
  40. extern asmlinkage void decstation_handle_int(void);
  41. extern asmlinkage void deskstation_rpc44_handle_int(void);
  42. extern asmlinkage void deskstation_tyne_handle_int(void);
  43. extern asmlinkage void mips_magnum_4000_handle_int(void);
  44. extern asmlinkage void handle_mod(void);
  45. extern asmlinkage void handle_tlbl(void);
  46. extern asmlinkage void handle_tlbs(void);
  47. extern asmlinkage void handle_adel(void);
  48. extern asmlinkage void handle_ades(void);
  49. extern asmlinkage void handle_ibe(void);
  50. extern asmlinkage void handle_dbe(void);
  51. extern asmlinkage void handle_sys(void);
  52. extern asmlinkage void handle_bp(void);
  53. extern asmlinkage void handle_ri(void);
  54. extern asmlinkage void handle_cpu(void);
  55. extern asmlinkage void handle_ov(void);
  56. extern asmlinkage void handle_tr(void);
  57. extern asmlinkage void handle_fpe(void);
  58. extern asmlinkage void handle_watch(void);
  59. extern asmlinkage void handle_mcheck(void);
  60. extern asmlinkage void handle_reserved(void);
  61. extern int fpu_emulator_cop1Handler(struct pt_regs *);
  62. char watch_available = 0;
  63. void (*ibe_board_handler)(struct pt_regs *regs);
  64. void (*dbe_board_handler)(struct pt_regs *regs);
  65. int kstack_depth_to_print = 24;
  66. /*
  67.  * These constant is for searching for possible module text segments.
  68.  * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
  69.  */
  70. #define MODULE_RANGE (8*1024*1024)
  71. #ifndef CONFIG_CPU_HAS_LLSC
  72. /*
  73.  * This stuff is needed for the userland ll-sc emulation for R2300
  74.  */
  75. void simulate_ll(struct pt_regs *regs, unsigned int opcode);
  76. void simulate_sc(struct pt_regs *regs, unsigned int opcode);
  77. #define OPCODE 0xfc000000
  78. #define BASE   0x03e00000
  79. #define RT     0x001f0000
  80. #define OFFSET 0x0000ffff
  81. #define LL     0xc0000000
  82. #define SC     0xe0000000
  83. #endif
  84. /*
  85.  * This routine abuses get_user()/put_user() to reference pointers
  86.  * with at least a bit of error checking ...
  87.  */
  88. void show_stack(unsigned int *sp)
  89. {
  90. int i;
  91. unsigned int *stack;
  92. stack = sp;
  93. i = 0;
  94. printk("Stack:");
  95. while ((unsigned long) stack & (PAGE_SIZE - 1)) {
  96. unsigned long stackdata;
  97. if (__get_user(stackdata, stack++)) {
  98. printk(" (Bad stack address)");
  99. break;
  100. }
  101. printk(" %08lx", stackdata);
  102. if (++i > 40) {
  103. printk(" ...");
  104. break;
  105. }
  106. if (i % 8 == 0)
  107. printk("n      ");
  108. }
  109. }
  110. void show_trace(unsigned int *sp)
  111. {
  112. int i;
  113. unsigned int *stack;
  114. unsigned long kernel_start, kernel_end;
  115. unsigned long module_start, module_end;
  116. extern char _stext, _etext;
  117. stack = sp;
  118. i = 0;
  119. kernel_start = (unsigned long) &_stext;
  120. kernel_end = (unsigned long) &_etext;
  121. module_start = VMALLOC_START;
  122. module_end = module_start + MODULE_RANGE;
  123. printk("nCall Trace:");
  124. while ((unsigned long) stack & (PAGE_SIZE -1)) {
  125. unsigned long addr;
  126. if (__get_user(addr, stack++)) {
  127. printk(" (Bad stack address)n");
  128. break;
  129. }
  130. /*
  131.  * If the address is either in the text segment of the
  132.  * kernel, or in the region which contains vmalloc'ed
  133.  * memory, it *may* be the address of a calling
  134.  * routine; if so, print it so that someone tracing
  135.  * down the cause of the crash will be able to figure
  136.  * out the call path that was taken.
  137.  */
  138. if ((addr >= kernel_start && addr < kernel_end) ||
  139.     (addr >= module_start && addr < module_end)) { 
  140. printk(" [<%08lx>]", addr);
  141. if (++i > 40) {
  142. printk(" ...");
  143. break;
  144. }
  145. }
  146. }
  147. }
  148. void show_code(unsigned int *pc)
  149. {
  150. long i;
  151. printk("nCode:");
  152. for(i = -3 ; i < 6 ; i++) {
  153. unsigned long insn;
  154. if (__get_user(insn, pc + i)) {
  155. printk(" (Bad address in epc)n");
  156. break;
  157. }
  158. printk("%c%08lx%c",(i?' ':'<'),insn,(i?' ':'>'));
  159. }
  160. }
  161. spinlock_t die_lock;
  162. extern void __die(const char * str, struct pt_regs * regs, const char *where,
  163.                   unsigned long line)
  164. {
  165. console_verbose();
  166. spin_lock_irq(&die_lock);
  167. printk("%s", str);
  168. if (where)
  169. printk(" in %s, line %ld", where, line);
  170. printk(":n");
  171. show_regs(regs);
  172. printk("Process %s (pid: %d, stackpage=%08lx)n",
  173. current->comm, current->pid, (unsigned long) current);
  174. show_stack((unsigned int *) regs->regs[29]);
  175. show_trace((unsigned int *) regs->regs[29]);
  176. show_code((unsigned int *) regs->cp0_epc);
  177. printk("n");
  178. spin_unlock_irq(&die_lock);
  179. do_exit(SIGSEGV);
  180. }
  181. void __die_if_kernel(const char * str, struct pt_regs * regs, const char *where,
  182. unsigned long line)
  183. {
  184. if (!user_mode(regs))
  185. __die(str, regs, where, line);
  186. }
  187. extern const struct exception_table_entry __start___dbe_table[];
  188. extern const struct exception_table_entry __stop___dbe_table[];
  189. void __declare_dbe_table(void)
  190. {
  191. __asm__ __volatile__(
  192. ".sectiont__dbe_table,"a"nt"
  193. ".previous"
  194. );
  195. }
  196. static inline unsigned long
  197. search_one_table(const struct exception_table_entry *first,
  198.  const struct exception_table_entry *last,
  199.  unsigned long value)
  200. {
  201. const struct exception_table_entry *mid;
  202. long diff;
  203. while (first < last) {
  204. mid = (last - first) / 2 + first;
  205. diff = mid->insn - value;
  206. if (diff < 0)
  207. first = mid + 1;
  208. else
  209. last = mid;
  210. }
  211. return (first == last && first->insn == value) ? first->nextinsn : 0;
  212. }
  213. extern spinlock_t modlist_lock;
  214. static inline unsigned long
  215. search_dbe_table(unsigned long addr)
  216. {
  217. unsigned long ret = 0;
  218. #ifndef CONFIG_MODULES
  219. /* There is only the kernel to search.  */
  220. ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr);
  221. return ret;
  222. #else
  223. unsigned long flags;
  224. /* The kernel is the last "module" -- no need to treat it special.  */
  225. struct module *mp;
  226. struct archdata *ap;
  227. spin_lock_irqsave(&modlist_lock, flags);
  228. for (mp = module_list; mp != NULL; mp = mp->next) {
  229. if (!mod_member_present(mp, archdata_end) ||
  230.              !mod_archdata_member_present(mp, struct archdata,
  231.  dbe_table_end))
  232. continue;
  233. ap = (struct archdata *)(mp->archdata_start);
  234. if (ap->dbe_table_start == NULL ||
  235.     !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING)))
  236. continue;
  237. ret = search_one_table(ap->dbe_table_start,
  238.        ap->dbe_table_end - 1, addr);
  239. if (ret)
  240. break;
  241. }
  242. spin_unlock_irqrestore(&modlist_lock, flags);
  243. return ret;
  244. #endif
  245. }
  246. static void default_be_board_handler(struct pt_regs *regs)
  247. {
  248. unsigned long new_epc;
  249. unsigned long fixup;
  250. int data = regs->cp0_cause & 4;
  251. if (data && !user_mode(regs)) {
  252. fixup = search_dbe_table(regs->cp0_epc);
  253. if (fixup) {
  254. new_epc = fixup_exception(dpf_reg, fixup,
  255.   regs->cp0_epc);
  256. regs->cp0_epc = new_epc;
  257. return;
  258. }
  259. }
  260. /*
  261.  * Assume it would be too dangerous to continue ...
  262.  */
  263. printk(KERN_ALERT "%s bus error, epc == %08lx, ra == %08lxn",
  264.        data ? "Data" : "Instruction",
  265.        regs->cp0_epc, regs->regs[31]);
  266. die_if_kernel("Oops", regs);
  267. force_sig(SIGBUS, current);
  268. }
  269. asmlinkage void do_ibe(struct pt_regs *regs)
  270. {
  271. ibe_board_handler(regs);
  272. }
  273. asmlinkage void do_dbe(struct pt_regs *regs)
  274. {
  275. dbe_board_handler(regs);
  276. }
  277. asmlinkage void do_ov(struct pt_regs *regs)
  278. {
  279. if (compute_return_epc(regs))
  280. return;
  281. force_sig(SIGFPE, current);
  282. }
  283. /*
  284.  * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
  285.  */
  286. asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
  287. {
  288. if (fcr31 & FPU_CSR_UNI_X) {
  289. extern void save_fp(struct task_struct *);
  290. extern void restore_fp(struct task_struct *);
  291. int sig;
  292. /*
  293.    * Unimplemented operation exception.  If we've got the
  294.    * full software emulator on-board, let's use it...
  295.  *
  296.  * Force FPU to dump state into task/thread context.
  297.  * We're moving a lot of data here for what is probably
  298.  * a single instruction, but the alternative is to 
  299.  * pre-decode the FP register operands before invoking
  300.  * the emulator, which seems a bit extreme for what
  301.  * should be an infrequent event.
  302.  */
  303. save_fp(current);
  304. /* Run the emulator */
  305. sig = fpu_emulator_cop1Handler(regs);
  306. /* 
  307.  * We can't allow the emulated instruction to leave the
  308.  * Unimplemented Operation bit set in $fcr31.
  309.  */
  310. current->thread.fpu.soft.sr &= ~FPU_CSR_UNI_X;
  311. /* Restore the hardware register state */
  312. restore_fp(current);
  313. /* If something went wrong, signal */
  314. if (sig)
  315. force_sig(sig, current);
  316. return;
  317. }
  318. if (compute_return_epc(regs))
  319. return;
  320. force_sig(SIGFPE, current);
  321. printk(KERN_DEBUG "Sent send SIGFPE to %sn", current->comm);
  322. }
  323. static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
  324. {
  325. unsigned int *epc;
  326. epc = (unsigned int *) regs->cp0_epc +
  327.       ((regs->cp0_cause & CAUSEF_BD) != 0);
  328. if (!get_user(*opcode, epc))
  329. return 0;
  330. force_sig(SIGSEGV, current);
  331. return 1;
  332. }
  333. asmlinkage void do_bp(struct pt_regs *regs)
  334. {
  335. siginfo_t info;
  336. unsigned int opcode, bcode;
  337. unsigned int *epc;
  338. epc = (unsigned int *) regs->cp0_epc +
  339.       ((regs->cp0_cause & CAUSEF_BD) != 0);
  340. if (get_user(opcode, epc))
  341. goto sigsegv;
  342. /*
  343.  * There is the ancient bug in the MIPS assemblers that the break
  344.  * code starts left to bit 16 instead to bit 6 in the opcode.
  345.  * Gas is bug-compatible ...
  346.  */
  347. bcode = ((opcode >> 16) & ((1 << 20) - 1));
  348. /*
  349.  * (A short test says that IRIX 5.3 sends SIGTRAP for all break
  350.  * insns, even for break codes that indicate arithmetic failures.
  351.  * Weird ...)
  352.  * But should we continue the brokenness???  --macro
  353.  */
  354. switch (bcode) {
  355. case 6:
  356. case 7:
  357. if (bcode == 7)
  358. info.si_code = FPE_INTDIV;
  359. else
  360. info.si_code = FPE_INTOVF;
  361. info.si_signo = SIGFPE;
  362. info.si_errno = 0;
  363. info.si_addr = (void *)compute_return_epc(regs);
  364. force_sig_info(SIGFPE, &info, current);
  365. break;
  366. default:
  367. force_sig(SIGTRAP, current);
  368. }
  369. return;
  370. sigsegv:
  371. force_sig(SIGSEGV, current);
  372. }
  373. asmlinkage void do_tr(struct pt_regs *regs)
  374. {
  375. siginfo_t info;
  376. unsigned int opcode, bcode;
  377. unsigned *epc;
  378. epc = (unsigned int *) regs->cp0_epc +
  379.       ((regs->cp0_cause & CAUSEF_BD) != 0);
  380. if (get_user(opcode, epc))
  381. goto sigsegv;
  382. bcode = ((opcode >> 6) & ((1 << 20) - 1));
  383. /*
  384.  * (A short test says that IRIX 5.3 sends SIGTRAP for all break
  385.  * insns, even for break codes that indicate arithmetic failures.
  386.  * Weird ...)
  387.  * But should we continue the brokenness???  --macro
  388.  */
  389. switch (bcode) {
  390. case 6:
  391. case 7:
  392. if (bcode == 7)
  393. info.si_code = FPE_INTDIV;
  394. else
  395. info.si_code = FPE_INTOVF;
  396. info.si_signo = SIGFPE;
  397. info.si_errno = 0;
  398. info.si_addr = (void *)compute_return_epc(regs);
  399. force_sig_info(SIGFPE, &info, current);
  400. break;
  401. default:
  402. force_sig(SIGTRAP, current);
  403. }
  404. return;
  405. sigsegv:
  406. force_sig(SIGSEGV, current);
  407. }
  408. #ifndef CONFIG_CPU_HAS_LLSC
  409. #ifdef CONFIG_SMP
  410. #error "ll/sc emulation is not SMP safe"
  411. #endif
  412. /*
  413.  * userland emulation for R2300 CPUs
  414.  * needed for the multithreading part of glibc
  415.  *
  416.  * this implementation can handle only sychronization between 2 or more
  417.  * user contexts and is not SMP safe.
  418.  */
  419. asmlinkage void do_ri(struct pt_regs *regs)
  420. {
  421. unsigned int opcode;
  422. if (!user_mode(regs))
  423. BUG();
  424. if (!get_insn_opcode(regs, &opcode)) {
  425. if ((opcode & OPCODE) == LL) {
  426. simulate_ll(regs, opcode);
  427. return;
  428. }
  429. if ((opcode & OPCODE) == SC) {
  430. simulate_sc(regs, opcode);
  431. return;
  432. }
  433. }
  434. if (compute_return_epc(regs))
  435. return;
  436. force_sig(SIGILL, current);
  437. }
  438. /*
  439.  * The ll_bit is cleared by r*_switch.S
  440.  */
  441. unsigned long ll_bit;
  442. #ifdef CONFIG_PROC_FS
  443. extern unsigned long ll_ops;
  444. extern unsigned long sc_ops;
  445. #endif
  446. static struct task_struct *ll_task = NULL;
  447. void simulate_ll(struct pt_regs *regp, unsigned int opcode)
  448. {
  449. unsigned long value, *vaddr;
  450. long offset;
  451. int signal = 0;
  452. /*
  453.  * analyse the ll instruction that just caused a ri exception
  454.  * and put the referenced address to addr.
  455.  */
  456. /* sign extend offset */
  457. offset = opcode & OFFSET;
  458. offset <<= 16;
  459. offset >>= 16;
  460. vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
  461. #ifdef CONFIG_PROC_FS
  462. ll_ops++;
  463. #endif
  464. if ((unsigned long)vaddr & 3)
  465. signal = SIGBUS;
  466. else if (get_user(value, vaddr))
  467. signal = SIGSEGV;
  468. else {
  469. if (ll_task == NULL || ll_task == current) {
  470. ll_bit = 1;
  471. } else {
  472. ll_bit = 0;
  473. }
  474. ll_task = current;
  475. regp->regs[(opcode & RT) >> 16] = value;
  476. }
  477. if (compute_return_epc(regp))
  478. return;
  479. if (signal)
  480. send_sig(signal, current, 1);
  481. }
  482. void simulate_sc(struct pt_regs *regp, unsigned int opcode)
  483. {
  484. unsigned long *vaddr, reg;
  485. long offset;
  486. int signal = 0;
  487. /*
  488.  * analyse the sc instruction that just caused a ri exception
  489.  * and put the referenced address to addr.
  490.  */
  491. /* sign extend offset */
  492. offset = opcode & OFFSET;
  493. offset <<= 16;
  494. offset >>= 16;
  495. vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
  496. reg = (opcode & RT) >> 16;
  497. #ifdef CONFIG_PROC_FS
  498. sc_ops++;
  499. #endif
  500. if ((unsigned long)vaddr & 3)
  501. signal = SIGBUS;
  502. else if (ll_bit == 0 || ll_task != current)
  503. regp->regs[reg] = 0;
  504. else if (put_user(regp->regs[reg], vaddr))
  505. signal = SIGSEGV;
  506. else
  507. regp->regs[reg] = 1;
  508. if (compute_return_epc(regp))
  509. return;
  510. if (signal)
  511. send_sig(signal, current, 1);
  512. }
  513. #else /* MIPS 2 or higher */
  514. asmlinkage void do_ri(struct pt_regs *regs)
  515. {
  516. unsigned int opcode;
  517. get_insn_opcode(regs, &opcode);
  518. if (compute_return_epc(regs))
  519. return;
  520. force_sig(SIGILL, current);
  521. }
  522. #endif
  523. asmlinkage void do_cpu(struct pt_regs *regs)
  524. {
  525. unsigned int cpid;
  526. extern void lazy_fpu_switch(void *);
  527. extern void init_fpu(void);
  528. void fpu_emulator_init_fpu(void);
  529. int sig;
  530. cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
  531. if (cpid != 1)
  532. goto bad_cid;
  533. if (!(mips_cpu.options & MIPS_CPU_FPU))
  534. goto fp_emul;
  535. regs->cp0_status |= ST0_CU1;
  536. if (last_task_used_math == current)
  537. return;
  538. if (current->used_math) { /* Using the FPU again.  */
  539. lazy_fpu_switch(last_task_used_math);
  540. } else { /* First time FPU user.  */
  541. init_fpu();
  542. current->used_math = 1;
  543. }
  544. last_task_used_math = current;
  545. return;
  546. fp_emul:
  547. if (last_task_used_math != current) {
  548. if (!current->used_math) {
  549. fpu_emulator_init_fpu();
  550. current->used_math = 1;
  551. }
  552. }
  553. sig = fpu_emulator_cop1Handler(regs);
  554. last_task_used_math = current;
  555. if (sig)
  556. force_sig(sig, current);
  557. return;
  558. bad_cid:
  559. force_sig(SIGILL, current);
  560. }
  561. asmlinkage void do_watch(struct pt_regs *regs)
  562. {
  563. /*
  564.  * We use the watch exception where available to detect stack
  565.  * overflows.
  566.  */
  567. show_regs(regs);
  568. panic("Caught WATCH exception - probably caused by stack overflow.");
  569. }
  570. asmlinkage void do_mcheck(struct pt_regs *regs)
  571. {
  572. show_regs(regs);
  573. panic("Caught Machine Check exception - probably caused by multiple "
  574.       "matching entries in the TLB.");
  575. }
  576. asmlinkage void do_reserved(struct pt_regs *regs)
  577. {
  578. /*
  579.  * Game over - no way to handle this if it ever occurs.  Most probably
  580.  * caused by a new unknown cpu type or after another deadly
  581.  * hard/software error.
  582.  */
  583. show_regs(regs);
  584. panic("Caught reserved exception - should not happen.");
  585. }
  586. static inline void watch_init(void)
  587. {
  588. if (mips_cpu.options & MIPS_CPU_WATCH ) {
  589. set_except_vector(23, handle_watch);
  590.   watch_available = 1;
  591.   }
  592. }
  593. /*
  594.  * Some MIPS CPUs can enable/disable for cache parity detection, but do
  595.  * it different ways.
  596.  */
  597. static inline void parity_protection_init(void)
  598. {
  599. switch (mips_cpu.cputype) {
  600. case CPU_5KC:
  601. /* Set the PE bit (bit 31) in the CP0_ECC register. */
  602. printk(KERN_INFO "Enable the cache parity protection for "
  603.        "MIPS 5KC CPUs.n");
  604. write_32bit_cp0_register(CP0_ECC,
  605.                          read_32bit_cp0_register(CP0_ECC)
  606.                          | 0x80000000); 
  607. break;
  608. default:
  609. break;
  610. }
  611. }
  612. asmlinkage void cache_parity_error(void)
  613. {
  614. unsigned int reg_val;
  615. /* For the moment, report the problem and hang. */
  616. reg_val = read_32bit_cp0_register(CP0_ERROREPC);
  617. printk("Cache error exception:n");
  618. printk("cp0_errorepc == %08xn", reg_val);
  619. reg_val = read_32bit_cp0_register(CP0_CACHEERR);
  620. printk("cp0_cacheerr == %08xn", reg_val);
  621. printk("Decoded CP0_CACHEERR: %s cache fault in %s reference.n",
  622.        reg_val & (1<<30) ? "secondary" : "primary",
  623.        reg_val & (1<<31) ? "data" : "insn");
  624. printk("Error bits: %s%s%s%s%s%s%sn",
  625.        reg_val & (1<<29) ? "ED " : "",
  626.        reg_val & (1<<28) ? "ET " : "",
  627.        reg_val & (1<<26) ? "EE " : "",
  628.        reg_val & (1<<25) ? "EB " : "",
  629.        reg_val & (1<<24) ? "EI " : "",
  630.        reg_val & (1<<23) ? "E1 " : "",
  631.        reg_val & (1<<22) ? "E0 " : "");
  632. printk("IDX: 0x%08xn", reg_val & ((1<<22)-1));
  633. if (reg_val&(1<<22))
  634. printk("DErrAddr0: 0x%08xn",
  635.        read_32bit_cp0_set1_register(CP0_S1_DERRADDR0));
  636. if (reg_val&(1<<23))
  637. printk("DErrAddr1: 0x%08xn",
  638.        read_32bit_cp0_set1_register(CP0_S1_DERRADDR1));
  639. panic("Can't handle the cache error!");
  640. }
  641. unsigned long exception_handlers[32];
  642. /*
  643.  * As a side effect of the way this is implemented we're limited
  644.  * to interrupt handlers in the address range from
  645.  * KSEG0 <= x < KSEG0 + 256mb on the Nevada.  Oh well ...
  646.  */
  647. void *set_except_vector(int n, void *addr)
  648. {
  649. unsigned handler = (unsigned long) addr;
  650. unsigned old_handler = exception_handlers[n];
  651. exception_handlers[n] = handler;
  652. if (n == 0 && mips_cpu.options & MIPS_CPU_DIVEC) {
  653. *(volatile u32 *)(KSEG0+0x200) = 0x08000000 |
  654.                                  (0x03ffffff & (handler >> 2));
  655. flush_icache_range(KSEG0+0x200, KSEG0 + 0x204);
  656. }
  657. return (void *)old_handler;
  658. }
  659. asmlinkage int (*save_fp_context)(struct sigcontext *sc);
  660. asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
  661. extern asmlinkage int _save_fp_context(struct sigcontext *sc);
  662. extern asmlinkage int _restore_fp_context(struct sigcontext *sc);
  663. extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
  664. extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
  665. void __init trap_init(void)
  666. {
  667. extern char except_vec0_nevada, except_vec0_r4000;
  668. extern char except_vec0_r4600, except_vec0_r2300;
  669. extern char except_vec1_generic, except_vec2_generic;
  670. extern char except_vec3_generic, except_vec3_r4000;
  671. extern char except_vec4;
  672. extern char except_vec_ejtag_debug;
  673. unsigned long i;
  674. /* Some firmware leaves the BEV flag set, clear it.  */
  675. clear_cp0_status(ST0_BEV);
  676. /* Copy the generic exception handler code to it's final destination. */
  677. memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80);
  678. memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
  679. memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
  680. flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x200);
  681. /*
  682.  * Setup default vectors
  683.  */
  684. for (i = 0; i <= 31; i++)
  685. set_except_vector(i, handle_reserved);
  686. /* 
  687.  * Copy the EJTAG debug exception vector handler code to it's final 
  688.  * destination.
  689.  */
  690. memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80);
  691. /*
  692.  * Only some CPUs have the watch exceptions or a dedicated
  693.  * interrupt vector.
  694.  */
  695. watch_init();
  696. /*
  697.  * Some MIPS CPUs have a dedicated interrupt vector which reduces the
  698.  * interrupt processing overhead.  Use it where available.
  699.  */
  700. if (mips_cpu.options & MIPS_CPU_DIVEC) {
  701. memcpy((void *)(KSEG0 + 0x200), &except_vec4, 8);
  702. set_cp0_cause(CAUSEF_IV);
  703. }
  704. /*
  705.  * Some CPUs can enable/disable for cache parity detection, but does
  706.  * it different ways.
  707.  */
  708. parity_protection_init();
  709. set_except_vector(1, handle_mod);
  710. set_except_vector(2, handle_tlbl);
  711. set_except_vector(3, handle_tlbs);
  712. set_except_vector(4, handle_adel);
  713. set_except_vector(5, handle_ades);
  714. /*
  715.  * The Data Bus Error/ Instruction Bus Errors are signaled
  716.  * by external hardware.  Therefore these two expection have
  717.  * board specific handlers.
  718.  */
  719. set_except_vector(6, handle_ibe);
  720. set_except_vector(7, handle_dbe);
  721. ibe_board_handler = default_be_board_handler;
  722. dbe_board_handler = default_be_board_handler;
  723. set_except_vector(8, handle_sys);
  724. set_except_vector(9, handle_bp);
  725. set_except_vector(10, handle_ri);
  726. set_except_vector(11, handle_cpu);
  727. set_except_vector(12, handle_ov);
  728. set_except_vector(13, handle_tr);
  729. if (mips_cpu.options & MIPS_CPU_FPU)
  730. set_except_vector(15, handle_fpe);
  731. /*
  732.  * Handling the following exceptions depends mostly of the cpu type
  733.  */
  734. if ((mips_cpu.options & MIPS_CPU_4KEX)
  735.     && (mips_cpu.options & MIPS_CPU_4KTLB)) {
  736. if (mips_cpu.cputype == CPU_NEVADA) {
  737. memcpy((void *)KSEG0, &except_vec0_nevada, 0x80);
  738. } else if (mips_cpu.cputype == CPU_R4600)
  739. memcpy((void *)KSEG0, &except_vec0_r4600, 0x80);
  740. else
  741. memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
  742. /* Cache error vector already set above.  */
  743. if (mips_cpu.options & MIPS_CPU_VCE) {
  744. memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
  745.        0x80);
  746. } else {
  747. memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
  748.        0x80);
  749. }
  750. if (mips_cpu.options & MIPS_CPU_FPU) {
  751.         save_fp_context = _save_fp_context;
  752. restore_fp_context = _restore_fp_context;
  753. } else {
  754.         save_fp_context = fpu_emulator_save_context;
  755. restore_fp_context = fpu_emulator_restore_context;
  756. }
  757. } else switch (mips_cpu.cputype) {
  758. case CPU_SB1:
  759. /*
  760.  * XXX - This should be folded in to the "cleaner" handling,
  761.  * above
  762.  */
  763. memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
  764. memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80);
  765. save_fp_context = _save_fp_context;
  766. restore_fp_context = _restore_fp_context;
  767. /* Enable timer interrupt and scd mapped interrupt */
  768. clear_cp0_status(0xf000);
  769. set_cp0_status(0xc00);
  770. break;
  771. case CPU_R6000:
  772. case CPU_R6000A:
  773.         save_fp_context = _save_fp_context;
  774. restore_fp_context = _restore_fp_context;
  775. /*
  776.  * The R6000 is the only R-series CPU that features a machine
  777.  * check exception (similar to the R4000 cache error) and
  778.  * unaligned ldc1/sdc1 exception.  The handlers have not been
  779.  * written yet.  Well, anyway there is no R6000 machine on the
  780.  * current list of targets for Linux/MIPS.
  781.  * (Duh, crap, there is someone with a tripple R6k machine)
  782.  */
  783. //set_except_vector(14, handle_mc);
  784. //set_except_vector(15, handle_ndc);
  785. case CPU_R2000:
  786. case CPU_R3000:
  787. case CPU_R3000A:
  788. case CPU_R3041:
  789. case CPU_R3051:
  790. case CPU_R3052:
  791. case CPU_R3081:
  792. case CPU_R3081E:
  793. case CPU_TX3912:
  794. case CPU_TX3922:
  795. case CPU_TX3927:
  796.         save_fp_context = _save_fp_context;
  797. restore_fp_context = _restore_fp_context;
  798. memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
  799. memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80);
  800. break;
  801. case CPU_UNKNOWN:
  802. default:
  803. panic("Unknown CPU type");
  804. }
  805. flush_icache_range(KSEG0, KSEG0 + 0x200);
  806. if (mips_cpu.isa_level == MIPS_CPU_ISA_IV)
  807. set_cp0_status(ST0_XX);
  808. atomic_inc(&init_mm.mm_count); /* XXX  UP?  */
  809. current->active_mm = &init_mm;
  810. write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23);
  811. current_pgd[0] = init_mm.pgd;
  812. }