traps.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:21k
源码类别:

Linux/Unix编程

开发平台:

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 by Ralf Baechle
  7.  * Copyright (C) 1995, 1996 Paul M. Antoine
  8.  * Copyright (C) 1998 Ulf Carlsson
  9.  * Copyright (C) 1999 Silicon Graphics, Inc.
  10.  * Copyright (C) 2002  Maciej W. Rozycki
  11.  */
  12. #include <linux/config.h>
  13. #include <linux/init.h>
  14. #include <linux/mm.h>
  15. #include <linux/module.h>
  16. #include <linux/sched.h>
  17. #include <linux/smp.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/spinlock.h>
  20. #include <asm/bootinfo.h>
  21. #include <asm/branch.h>
  22. #include <asm/cpu.h>
  23. #include <asm/module.h>
  24. #include <asm/pgtable.h>
  25. #include <asm/io.h>
  26. #include <asm/ptrace.h>
  27. #include <asm/watch.h>
  28. #include <asm/system.h>
  29. #include <asm/traps.h>
  30. #include <asm/uaccess.h>
  31. #include <asm/mmu_context.h>
  32. #include <asm/cachectl.h>
  33. #include <asm/types.h>
  34. extern asmlinkage void __xtlb_mod(void);
  35. extern asmlinkage void __xtlb_tlbl(void);
  36. extern asmlinkage void __xtlb_tlbs(void);
  37. extern asmlinkage void handle_adel(void);
  38. extern asmlinkage void handle_ades(void);
  39. extern asmlinkage void handle_ibe(void);
  40. extern asmlinkage void handle_dbe(void);
  41. extern asmlinkage void handle_sys(void);
  42. extern asmlinkage void handle_bp(void);
  43. extern asmlinkage void handle_ri(void);
  44. extern asmlinkage void handle_cpu(void);
  45. extern asmlinkage void handle_ov(void);
  46. extern asmlinkage void handle_tr(void);
  47. extern asmlinkage void handle_fpe(void);
  48. extern asmlinkage void handle_watch(void);
  49. extern asmlinkage void handle_mcheck(void);
  50. extern asmlinkage void handle_reserved(void);
  51. extern int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,
  52. struct mips_fpu_soft_struct *ctx);
  53. void fpu_emulator_init_fpu(void);
  54. char watch_available = 0;
  55. char dedicated_iv_available = 0;
  56. int (*be_board_handler)(struct pt_regs *regs, int is_fixup);
  57. int kstack_depth_to_print = 24;
  58. /*
  59.  * These constant is for searching for possible module text segments.
  60.  * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
  61.  */
  62. #define MODULE_RANGE (8*1024*1024)
  63. #define OPCODE 0xfc000000
  64. /*
  65.  * If the address is either in the .text section of the
  66.  * kernel, or in the vmalloc'ed module regions, it *may*
  67.  * be the address of a calling routine
  68.  */
  69. #ifdef CONFIG_MODULES
  70. extern struct module *module_list;
  71. extern struct module kernel_module;
  72. static inline int kernel_text_address(long addr)
  73. {
  74. extern char _stext, _etext;
  75. int retval = 0;
  76. struct module *mod;
  77. if (addr >= (long) &_stext && addr <= (long) &_etext)
  78. return 1;
  79. for (mod = module_list; mod != &kernel_module; mod = mod->next) {
  80. /* mod_bound tests for addr being inside the vmalloc'ed
  81.  * module area. Of course it'd be better to test only
  82.  * for the .text subset... */
  83. if (mod_bound(addr, 0, mod)) {
  84. retval = 1;
  85. break;
  86. }
  87. }
  88. return retval;
  89. }
  90. #else
  91. static inline int kernel_text_address(long addr)
  92. {
  93. extern char _stext, _etext;
  94. return (addr >= (long) &_stext && addr <= (long) &_etext);
  95. }
  96. #endif
  97. /*
  98.  * This routine abuses get_user()/put_user() to reference pointers
  99.  * with at least a bit of error checking ...
  100.  */
  101. void show_stack(long *sp)
  102. {
  103. int i;
  104. long stackdata;
  105. printk("Stack:");
  106. i = 0;
  107. while ((long) sp & (PAGE_SIZE - 1)) {
  108. if (i && ((i % 4) == 0))
  109. printk("n      ");
  110. if (i > 40) {
  111. printk(" ...");
  112. break;
  113. }
  114. if (__get_user(stackdata, sp++)) {
  115. printk(" (Bad stack address)");
  116. break;
  117. }
  118. printk(" %016lx", stackdata);
  119. i++;
  120. }
  121. printk("n");
  122. }
  123. void show_trace(long *sp)
  124. {
  125. int i;
  126. long addr;
  127. printk("Call Trace:");
  128. i = 0;
  129. while ((long) sp & (PAGE_SIZE - 1)) {
  130. if (__get_user(addr, sp++)) {
  131. if (i && ((i % 3) == 0))
  132. printk("n           ");
  133. printk(" (Bad stack address)n");
  134. break;
  135. }
  136. /*
  137.  * If the address is either in the text segment of the
  138.  * kernel, or in the region which contains vmalloc'ed
  139.  * memory, it *may* be the address of a calling
  140.  * routine; if so, print it so that someone tracing
  141.  * down the cause of the crash will be able to figure
  142.  * out the call path that was taken.
  143.  */
  144. if (kernel_text_address(addr)) {
  145. if (i && ((i % 3) == 0))
  146. printk("n           ");
  147. if (i > 40) {
  148. printk(" ...");
  149. break;
  150. }
  151. printk(" [<%016lx>]", addr);
  152. i++;
  153. }
  154. }
  155. printk("n");
  156. }
  157. void show_trace_task(struct task_struct *tsk)
  158. {
  159. show_trace((long *)tsk->thread.reg29);
  160. }
  161. void show_code(unsigned int *pc)
  162. {
  163. long i;
  164. printk("nCode:");
  165. for(i = -3 ; i < 6 ; i++) {
  166. unsigned int insn;
  167. if (__get_user(insn, pc + i)) {
  168. printk(" (Bad address in epc)n");
  169. break;
  170. }
  171. printk("%c%08x%c",(i?' ':'<'),insn,(i?' ':'>'));
  172. }
  173. }
  174. void show_regs(struct pt_regs *regs)
  175. {
  176. printk("Cpu %dn", smp_processor_id());
  177. /* Saved main processor registers. */
  178. printk("$0      : %016lx %016lx %016lx %016lxn",
  179.        0UL, regs->regs[1], regs->regs[2], regs->regs[3]);
  180. printk("$4      : %016lx %016lx %016lx %016lxn",
  181.                regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
  182. printk("$8      : %016lx %016lx %016lx %016lxn",
  183.        regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]);
  184. printk("$12     : %016lx %016lx %016lx %016lxn",
  185.                regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
  186. printk("$16     : %016lx %016lx %016lx %016lxn",
  187.        regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]);
  188. printk("$20     : %016lx %016lx %016lx %016lxn",
  189.                regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
  190. printk("$24     : %016lx %016lxn",
  191.        regs->regs[24], regs->regs[25]);
  192. printk("$28     : %016lx %016lx %016lx %016lxn",
  193.        regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]);
  194. printk("Hi      : %016lxn", regs->hi);
  195. printk("Lo      : %016lxn", regs->lo);
  196. /* Saved cp0 registers. */
  197. printk("epc     : %016lx    %snbadvaddr: %016lxn",
  198.        regs->cp0_epc, print_tainted(), regs->cp0_badvaddr);
  199. printk("Status  : %08x  [ ", (unsigned int) regs->cp0_status);
  200. if (regs->cp0_status & ST0_KX) printk("KX ");
  201. if (regs->cp0_status & ST0_SX) printk("SX ");
  202. if (regs->cp0_status & ST0_UX) printk("UX ");
  203. switch (regs->cp0_status & ST0_KSU) {
  204. case KSU_USER: printk("USER "); break;
  205. case KSU_SUPERVISOR: printk("SUPERVISOR "); break;
  206. case KSU_KERNEL: printk("KERNEL "); break;
  207. default: printk("BAD_MODE "); break;
  208. }
  209. if (regs->cp0_status & ST0_ERL) printk("ERL ");
  210. if (regs->cp0_status & ST0_EXL) printk("EXL ");
  211. if (regs->cp0_status & ST0_IE) printk("IE ");
  212. printk("]n");
  213. printk("Cause   : %08xn", (unsigned int) regs->cp0_cause);
  214. }
  215. void show_registers(struct pt_regs *regs)
  216. {
  217. show_regs(regs);
  218. printk("Process %s (pid: %d, stackpage=%016lx)n",
  219. current->comm, current->pid, (unsigned long) current);
  220. show_stack((long *) regs->regs[29]);
  221. show_trace((long *) regs->regs[29]);
  222. show_code((unsigned int *) regs->cp0_epc);
  223. printk("n");
  224. }
  225. static spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
  226. void __die(const char * str, struct pt_regs * regs, const char * file,
  227.    const char * func, unsigned long line)
  228. {
  229. console_verbose();
  230. spin_lock_irq(&die_lock);
  231. printk("%s", str);
  232. if (file && func)
  233. printk(" in %s:%s, line %ld", file, func, line);
  234. printk(":n");
  235. show_registers(regs);
  236. spin_unlock_irq(&die_lock);
  237. do_exit(SIGSEGV);
  238. }
  239. void __die_if_kernel(const char * str, struct pt_regs * regs,
  240.      const char * file, const char * func, unsigned long line)
  241. {
  242. if (!user_mode(regs))
  243. __die(str, regs, file, func, line);
  244. }
  245. extern const struct exception_table_entry __start___dbe_table[];
  246. extern const struct exception_table_entry __stop___dbe_table[];
  247. void __declare_dbe_table(void)
  248. {
  249. __asm__ __volatile__(
  250. ".sectiont__dbe_table,"a"nt"
  251. ".previous"
  252. );
  253. }
  254. static inline unsigned long
  255. search_one_table(const struct exception_table_entry *first,
  256.  const struct exception_table_entry *last,
  257.  unsigned long value)
  258. {
  259. const struct exception_table_entry *mid;
  260. long diff;
  261. while (first < last) {
  262. mid = (last - first) / 2 + first;
  263. diff = mid->insn - value;
  264. if (diff < 0)
  265. first = mid + 1;
  266. else
  267. last = mid;
  268. }
  269. return (first == last && first->insn == value) ? first->nextinsn : 0;
  270. }
  271. extern spinlock_t modlist_lock;
  272. static inline unsigned long
  273. search_dbe_table(unsigned long addr)
  274. {
  275. unsigned long ret = 0;
  276. #ifndef CONFIG_MODULES
  277. /* There is only the kernel to search.  */
  278. ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr);
  279. return ret;
  280. #else
  281. unsigned long flags;
  282. /* The kernel is the last "module" -- no need to treat it special.  */
  283. struct module *mp;
  284. struct archdata *ap;
  285. spin_lock_irqsave(&modlist_lock, flags);
  286. for (mp = module_list; mp != NULL; mp = mp->next) {
  287. if (!mod_member_present(mp, archdata_end) ||
  288.              !mod_archdata_member_present(mp, struct archdata,
  289.  dbe_table_end))
  290. continue;
  291. ap = (struct archdata *)(mp->archdata_start);
  292. if (ap->dbe_table_start == NULL ||
  293.     !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING)))
  294. continue;
  295. ret = search_one_table(ap->dbe_table_start,
  296.        ap->dbe_table_end - 1, addr);
  297. if (ret)
  298. break;
  299. }
  300. spin_unlock_irqrestore(&modlist_lock, flags);
  301. return ret;
  302. #endif
  303. }
  304. asmlinkage void do_be(struct pt_regs *regs)
  305. {
  306. unsigned long new_epc;
  307. unsigned long fixup = 0;
  308. int data = regs->cp0_cause & 4;
  309. int action = MIPS_BE_FATAL;
  310. if (data && !user_mode(regs))
  311. fixup = search_dbe_table(regs->cp0_epc);
  312. if (fixup)
  313. action = MIPS_BE_FIXUP;
  314. if (be_board_handler)
  315. action = be_board_handler(regs, fixup != 0);
  316. switch (action) {
  317. case MIPS_BE_DISCARD:
  318. return;
  319. case MIPS_BE_FIXUP:
  320. if (fixup) {
  321. new_epc = fixup_exception(dpf_reg, fixup,
  322.   regs->cp0_epc);
  323. regs->cp0_epc = new_epc;
  324. return;
  325. }
  326. break;
  327. default:
  328. break;
  329. }
  330. /*
  331.  * Assume it would be too dangerous to continue ...
  332.  */
  333. printk(KERN_ALERT "%s bus error, epc == %08lx, ra == %08lxn",
  334.        data ? "Data" : "Instruction",
  335.        regs->cp0_epc, regs->regs[31]);
  336. die_if_kernel("Oops", regs);
  337. force_sig(SIGBUS, current);
  338. }
  339. asmlinkage void do_ov(struct pt_regs *regs)
  340. {
  341. siginfo_t info;
  342. if (compute_return_epc(regs))
  343. return;
  344. info.si_code = FPE_INTOVF;
  345. info.si_signo = SIGFPE;
  346. info.si_errno = 0;
  347. info.si_addr = (void *)regs->cp0_epc;
  348. force_sig_info(SIGFPE, &info, current);
  349. }
  350. /*
  351.  * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
  352.  */
  353. asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
  354. {
  355. if (fcr31 & FPU_CSR_UNI_X) {
  356. int sig;
  357. /*
  358.    * Unimplemented operation exception.  If we've got the full
  359.  * software emulator on-board, let's use it...
  360.  *
  361.  * Force FPU to dump state into task/thread context.  We're
  362.  * moving a lot of data here for what is probably a single
  363.  * instruction, but the alternative is to pre-decode the FP
  364.  * register operands before invoking the emulator, which seems
  365.  * a bit extreme for what should be an infrequent event.
  366.  */
  367. save_fp(current);
  368. /* Run the emulator */
  369. sig = fpu_emulator_cop1Handler (0, regs,
  370. &current->thread.fpu.soft);
  371. /*
  372.  * We can't allow the emulated instruction to leave any of
  373.  * the cause bit set in $fcr31.
  374.  */
  375. current->thread.fpu.soft.sr &= ~FPU_CSR_ALL_X;
  376. /* Restore the hardware register state */
  377. restore_fp(current);
  378. /* If something went wrong, signal */
  379. if (sig)
  380. {
  381. /*
  382.  * Return EPC is not calculated in the FPU emulator,
  383.  * if a signal is being send. So we calculate it here.
  384.  */
  385. compute_return_epc(regs);
  386. force_sig(sig, current);
  387. }
  388. return;
  389. }
  390. if (compute_return_epc(regs))
  391. return;
  392. force_sig(SIGFPE, current);
  393. }
  394. static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
  395. {
  396. unsigned long *epc;
  397. epc = (unsigned long *) regs->cp0_epc +
  398.       ((regs->cp0_cause & CAUSEF_BD) != 0);
  399. if (!get_user(opcode, epc))
  400. return 0;
  401. force_sig(SIGSEGV, current);
  402. return 1;
  403. }
  404. asmlinkage void do_bp(struct pt_regs *regs)
  405. {
  406. unsigned int opcode, bcode;
  407. siginfo_t info;
  408. if (get_insn_opcode(regs, &opcode))
  409. return;
  410. /*
  411.  * There is the ancient bug in the MIPS assemblers that the break
  412.  * code starts left to bit 16 instead to bit 6 in the opcode.
  413.  * Gas is bug-compatible ...
  414.  */
  415. bcode = ((opcode >> 16) & ((1 << 20) - 1));
  416. /*
  417.  * (A short test says that IRIX 5.3 sends SIGTRAP for all break
  418.  * insns, even for break codes that indicate arithmetic failures.
  419.  * Weird ...)
  420.  * But should we continue the brokenness???  --macro
  421.  */
  422. switch (bcode) {
  423. case 6:
  424. case 7:
  425. if (bcode == 7)
  426. info.si_code = FPE_INTDIV;
  427. else
  428. info.si_code = FPE_INTOVF;
  429. info.si_signo = SIGFPE;
  430. info.si_errno = 0;
  431. info.si_addr = (void *)regs->cp0_epc;
  432. force_sig_info(SIGFPE, &info, current);
  433. break;
  434. default:
  435. force_sig(SIGTRAP, current);
  436. }
  437. }
  438. asmlinkage void do_tr(struct pt_regs *regs)
  439. {
  440. unsigned int opcode, tcode = 0;
  441. siginfo_t info;
  442. if (get_insn_opcode(regs, &opcode))
  443. return;
  444.         /* Immediate versions don't provide a code.  */
  445. if (!(opcode & OPCODE))
  446. tcode = ((opcode >> 6) & ((1 << 20) - 1));
  447. /*
  448.  * (A short test says that IRIX 5.3 sends SIGTRAP for all trap
  449.  * insns, even for trap codes that indicate arithmetic failures.
  450.  * Weird ...)
  451.  * But should we continue the brokenness???  --macro
  452.  */
  453. switch (tcode) {
  454. case 6:
  455. case 7:
  456. if (tcode == 7)
  457. info.si_code = FPE_INTDIV;
  458. else
  459. info.si_code = FPE_INTOVF;
  460. info.si_signo = SIGFPE;
  461. info.si_errno = 0;
  462. info.si_addr = (void *)regs->cp0_epc;
  463. force_sig_info(SIGFPE, &info, current);
  464. break;
  465. default:
  466. force_sig(SIGTRAP, current);
  467. }
  468. }
  469. asmlinkage void do_ri(struct pt_regs *regs)
  470. {
  471. die_if_kernel("Reserved instruction in kernel code", regs);
  472. if (compute_return_epc(regs))
  473. return;
  474. force_sig(SIGILL, current);
  475. }
  476. asmlinkage void do_cpu(struct pt_regs *regs)
  477. {
  478. unsigned int cpid;
  479. void fpu_emulator_init_fpu(void);
  480. int sig;
  481. cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
  482. if (cpid != 1)
  483. goto bad_cid;
  484. if (!(mips_cpu.options & MIPS_CPU_FPU))
  485. goto fp_emul;
  486. regs->cp0_status |= ST0_CU1;
  487. #ifdef CONFIG_SMP
  488. if (current->used_math) {
  489. lazy_fpu_switch(0, current);
  490. } else {
  491. init_fpu();
  492. current->used_math = 1;
  493. }
  494. current->flags |= PF_USEDFPU;
  495. #else
  496. if (last_task_used_math == current)
  497. return;
  498. if (current->used_math) { /* Using the FPU again.  */
  499. lazy_fpu_switch(last_task_used_math, current);
  500. } else { /* First time FPU user.  */
  501. lazy_fpu_switch(last_task_used_math, 0);
  502. init_fpu();
  503. current->used_math = 1;
  504. }
  505. last_task_used_math = current;
  506. #endif
  507. return;
  508. fp_emul:
  509. if (last_task_used_math != current) {
  510. if (!current->used_math) {
  511. fpu_emulator_init_fpu();
  512. current->used_math = 1;
  513. }
  514. }
  515. sig = fpu_emulator_cop1Handler(0, regs, &current->thread.fpu.soft);
  516. last_task_used_math = current;
  517. if (sig) {
  518. /*
  519.  * Return EPC is not calculated in the FPU emulator, if
  520.  * a signal is being send. So we calculate it here.
  521.  */
  522. compute_return_epc(regs);
  523. force_sig(sig, current);
  524. }
  525. return;
  526. bad_cid:
  527. compute_return_epc(regs);
  528. force_sig(SIGILL, current);
  529. }
  530. asmlinkage void do_watch(struct pt_regs *regs)
  531. {
  532. extern void dump_tlb_all(void);
  533. /*
  534.  * We use the watch exception where available to detect stack
  535.  * overflows.
  536.  */
  537. dump_tlb_all();
  538. show_regs(regs);
  539. panic("Caught WATCH exception - probably caused by stack overflow.");
  540. }
  541. asmlinkage void do_mcheck(struct pt_regs *regs)
  542. {
  543. show_regs(regs);
  544. dump_tlb_all();
  545. /*
  546.  * Some chips may have other causes of machine check (e.g. SB1
  547.  * graduation timer)
  548.  */
  549. panic("Caught Machine Check exception - %scaused by multiple "
  550.       "matching entries in the TLB.",
  551.       (regs->cp0_status & ST0_TS) ? "" : "not ");
  552. }
  553. asmlinkage void do_reserved(struct pt_regs *regs)
  554. {
  555. /*
  556.  * Game over - no way to handle this if it ever occurs.  Most probably
  557.  * caused by a new unknown cpu type or after another deadly
  558.  * hard/software error.
  559.  */
  560. panic("Caught reserved exception %ld - should not happen.",
  561.       (regs->cp0_cause & 0x1f) >> 2);
  562. }
  563. static inline void watch_init(unsigned long cputype)
  564. {
  565. switch(cputype) {
  566. case CPU_R10000:
  567. case CPU_R4000MC:
  568. case CPU_R4400MC:
  569. case CPU_R4000SC:
  570. case CPU_R4400SC:
  571. case CPU_R4000PC:
  572. case CPU_R4400PC:
  573. case CPU_R4200:
  574. case CPU_R4300:
  575. set_except_vector(23, handle_watch);
  576. watch_available = 1;
  577. break;
  578. }
  579. }
  580. unsigned long exception_handlers[32];
  581. /*
  582.  * As a side effect of the way this is implemented we're limited
  583.  * to interrupt handlers in the address range from
  584.  * KSEG0 <= x < KSEG0 + 256mb on the Nevada.  Oh well ...
  585.  */
  586. void *set_except_vector(int n, void *addr)
  587. {
  588. unsigned long handler = (unsigned long) addr;
  589. unsigned long old_handler = exception_handlers[n];
  590. exception_handlers[n] = handler;
  591. if (n == 0 && mips_cpu.options & MIPS_CPU_DIVEC) {
  592. *(volatile u32 *)(KSEG0+0x200) = 0x08000000 |
  593.                                  (0x03ffffff & (handler >> 2));
  594. flush_icache_range(KSEG0+0x200, KSEG0 + 0x204);
  595. }
  596. return (void *)old_handler;
  597. }
  598. asmlinkage int (*save_fp_context)(struct sigcontext *sc);
  599. asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
  600. extern asmlinkage int _save_fp_context(struct sigcontext *sc);
  601. extern asmlinkage int _restore_fp_context(struct sigcontext *sc);
  602. extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
  603. extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
  604. void __init per_cpu_trap_init(void)
  605. {
  606. unsigned int cpu = smp_processor_id();
  607. /* Some firmware leaves the BEV flag set, clear it.  */
  608. clear_cp0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_BEV);
  609. set_cp0_status(ST0_CU0|ST0_FR|ST0_KX|ST0_SX|ST0_UX);
  610. /*
  611.  * Some MIPS CPUs have a dedicated interrupt vector which reduces the
  612.  * interrupt processing overhead.  Use it where available.
  613.  */
  614. if (mips_cpu.options & MIPS_CPU_DIVEC)
  615. set_cp0_cause(CAUSEF_IV);
  616. cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
  617. set_context(((long)(&pgd_current[cpu])) << 23);
  618. set_wired(0);
  619. }
  620. void __init trap_init(void)
  621. {
  622. extern char except_vec0;
  623. extern char except_vec1_r4k;
  624. extern char except_vec1_r10k;
  625. extern char except_vec2_generic;
  626. extern char except_vec3_generic, except_vec3_r4000;
  627. extern char except_vec4;
  628. unsigned long i;
  629. int dummy;
  630. per_cpu_trap_init();
  631. /* Copy the generic exception handlers to their final destination. */
  632. memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
  633. memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
  634. /*
  635.  * Setup default vectors
  636.  */
  637. for(i = 0; i <= 31; i++)
  638. set_except_vector(i, handle_reserved);
  639. /*
  640.  * Only some CPUs have the watch exceptions or a dedicated
  641.  * interrupt vector.
  642.  */
  643. watch_init(mips_cpu.cputype);
  644. /*
  645.  * Some MIPS CPUs have a dedicated interrupt vector which reduces the
  646.  * interrupt processing overhead.  Use it where available.
  647.  */
  648. memcpy((void *)(KSEG0 + 0x200), &except_vec4, 8);
  649. if (mips_cpu.options & MIPS_CPU_MCHECK)
  650. set_except_vector(24, handle_mcheck);
  651. /*
  652.  * The Data Bus Errors / Instruction Bus Errors are signaled
  653.  * by external hardware.  Therefore these two exceptions
  654.  * may have board specific handlers.
  655.  */
  656. bus_error_init();
  657. /*
  658.  * Handling the following exceptions depends mostly of the cpu type
  659.  */
  660. switch(mips_cpu.cputype) {
  661.         case CPU_SB1:
  662. #ifdef CONFIG_SB1_CACHE_ERROR
  663. {
  664. /* Special cache error handler for SB1 */
  665. extern char except_vec2_sb1;
  666. memcpy((void *)(KSEG0 + 0x100), &except_vec2_sb1, 0x80);
  667. memcpy((void *)(KSEG1 + 0x100), &except_vec2_sb1, 0x80);
  668. }
  669. #endif
  670. /* Enable timer interrupt and scd mapped interrupt */
  671. clear_cp0_status(0xf000);
  672. set_cp0_status(0xc00);
  673. /* Fall through. */
  674. case CPU_R10000:
  675. case CPU_R4000MC:
  676. case CPU_R4400MC:
  677. case CPU_R4000SC:
  678. case CPU_R4400SC:
  679. case CPU_R4000PC:
  680. case CPU_R4400PC:
  681. case CPU_R4200:
  682. case CPU_R4300:
  683. case CPU_R4600:
  684. case CPU_R5000:
  685. case CPU_NEVADA:
  686. case CPU_5KC:
  687. case CPU_20KC:
  688. case CPU_RM7000:
  689. /* Debug TLB refill handler.  */
  690. memcpy((void *)KSEG0, &except_vec0, 0x80);
  691. if ((mips_cpu.options & MIPS_CPU_4KEX)
  692.     && (mips_cpu.options & MIPS_CPU_4KTLB)) {
  693. memcpy((void *)KSEG0 + 0x080, &except_vec1_r4k, 0x80);
  694. } else {
  695. memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80);
  696. }
  697. if (mips_cpu.options & MIPS_CPU_VCE) {
  698. memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
  699.        0x80);
  700. } else {
  701. memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
  702.        0x80);
  703. }
  704. set_except_vector(1, __xtlb_mod);
  705. set_except_vector(2, __xtlb_tlbl);
  706. set_except_vector(3, __xtlb_tlbs);
  707. set_except_vector(4, handle_adel);
  708. set_except_vector(5, handle_ades);
  709. set_except_vector(6, handle_ibe);
  710. set_except_vector(7, handle_dbe);
  711. set_except_vector(8, handle_sys);
  712. set_except_vector(9, handle_bp);
  713. set_except_vector(10, handle_ri);
  714. set_except_vector(11, handle_cpu);
  715. set_except_vector(12, handle_ov);
  716. set_except_vector(13, handle_tr);
  717. set_except_vector(15, handle_fpe);
  718. break;
  719. case CPU_R8000:
  720. panic("R8000 is unsupported");
  721. break;
  722. case CPU_UNKNOWN:
  723. default:
  724. panic("Unknown CPU type");
  725. }
  726. flush_icache_range(KSEG0, KSEG0 + 0x200);
  727. if (mips_cpu.options & MIPS_CPU_FPU) {
  728.         save_fp_context = _save_fp_context;
  729. restore_fp_context = _restore_fp_context;
  730. } else {
  731. save_fp_context = fpu_emulator_save_context;
  732. restore_fp_context = fpu_emulator_restore_context;
  733. }
  734. if (mips_cpu.isa_level == MIPS_CPU_ISA_IV)
  735. set_cp0_status(ST0_XX);
  736. atomic_inc(&init_mm.mm_count); /* XXX UP?  */
  737. current->active_mm = &init_mm;
  738. }