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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/parisc/traps.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  *  Copyright (C) 1999, 2000  Philipp Rumpf <prumpf@tux.org>
  6.  */
  7. /*
  8.  * 'Traps.c' handles hardware traps and faults after we have saved some
  9.  * state in 'asm.s'.
  10.  */
  11. #include <linux/config.h>
  12. #include <linux/sched.h>
  13. #include <linux/kernel.h>
  14. #include <linux/string.h>
  15. #include <linux/errno.h>
  16. #include <linux/ptrace.h>
  17. #include <linux/timer.h>
  18. #include <linux/mm.h>
  19. #include <linux/smp.h>
  20. #include <linux/smp_lock.h>
  21. #include <linux/spinlock.h>
  22. #include <linux/init.h>
  23. #include <linux/interrupt.h>
  24. #include <asm/system.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/io.h>
  27. #include <asm/irq.h>
  28. #include <asm/atomic.h>
  29. #include <asm/smp.h>
  30. #include <asm/pdc.h>
  31. #ifdef CONFIG_KWDB
  32. #include <kdb/break.h> /* for BI2_KGDB_GDB */
  33. #include <kdb/kgdb_types.h> /* for __() */
  34. #include <kdb/save_state.h> /* for struct save_state */
  35. #include <kdb/kgdb_machine.h> /* for pt_regs_to_ssp and ssp_to_pt_regs */
  36. #include <kdb/trap.h> /* for I_BRK_INST */
  37. #endif /* CONFIG_KWDB */
  38. static inline void console_verbose(void)
  39. {
  40. console_loglevel = 15;
  41. }
  42. void page_exception(void);
  43. /*
  44.  * These constants are for searching for possible module text
  45.  * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
  46.  * a guess of how much space is likely to be vmalloced.
  47.  */
  48. #define VMALLOC_OFFSET (8*1024*1024)
  49. #define MODULE_RANGE (8*1024*1024)
  50. int kstack_depth_to_print = 24;
  51. static void printbinary(unsigned long x, int nbits)
  52. {
  53. unsigned long mask = 1UL << (nbits - 1);
  54. while (mask != 0) {
  55. printk(mask & x ? "1" : "0");
  56. mask >>= 1;
  57. }
  58. }
  59. void show_regs(struct pt_regs *regs)
  60. {
  61. int i;
  62. #ifdef __LP64__
  63. #define RFMT " %016lx"
  64. #else
  65. #define RFMT " %08lx"
  66. #endif
  67. printk("n"); /* don't want to have that pretty register dump messed up */
  68. printk("     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDInPSW: ");
  69. printbinary(regs->gr[0], 32);
  70. printk("    %sn", print_tainted());
  71. for (i = 0; i < 32; i += 4) {
  72. int j;
  73. printk("r%d-%dt", i, i + 3);
  74. for (j = 0; j < 4; j++) {
  75. printk(RFMT, i + j == 0 ? 0 : regs->gr[i + j]);
  76. }
  77. printk("n");
  78. }
  79. for (i = 0; i < 8; i += 4) {
  80. int j;
  81. printk("sr%d-%dt", i, i + 4);
  82. for (j = 0; j < 4; j++) {
  83. printk(RFMT, regs->sr[i + j]);
  84. }
  85. printk("n");
  86. }
  87. #if REDICULOUSLY_VERBOSE
  88. for (i = 0; i < 32; i++) {
  89. printk("FR%2d : %016lx  ", i, regs->fr[i]);
  90. if ((i & 1) == 1)
  91. printk("n");
  92. }
  93. #endif
  94. printk("nIASQ:" RFMT RFMT " IAOQ:" RFMT RFMT "n",
  95.        regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);
  96. printk(" IIR: %08lx    ISR:" RFMT "  IOR:" RFMT "nORIG_R28:" RFMT
  97.        "n", regs->iir, regs->isr, regs->ior, regs->orig_r28);
  98. }
  99. void
  100. die_if_kernel (char *str, struct pt_regs *regs, long err)
  101. {
  102. if (user_mode(regs)) {
  103. #if 1
  104. if (err == 0)
  105. return; /* STFU */
  106. /* XXX for debugging only */
  107. printk ("!!die_if_kernel: %s(%d): %s %ldn",
  108. current->comm, current->pid, str, err);
  109. show_regs(regs);
  110. #endif
  111. return;
  112. }
  113. printk("%s[%d]: %s %ldn", current->comm, current->pid, str, err);
  114. show_regs(regs);
  115. /* Wot's wrong wif bein' racy? */
  116. if (current->thread.flags & PARISC_KERNEL_DEATH) {
  117. printk("die_if_kernel recursion detected.n");
  118. sti();
  119. while (1);
  120. }
  121. current->thread.flags |= PARISC_KERNEL_DEATH;
  122. do_exit(SIGSEGV);
  123. }
  124. asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code)
  125. {
  126. }
  127. asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
  128. {
  129. }
  130. #ifndef CONFIG_MATH_EMULATION
  131. asmlinkage void math_emulate(long arg)
  132. {
  133. }
  134. #endif /* CONFIG_MATH_EMULATION */
  135. int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
  136. {
  137. return syscall(regs);
  138. }
  139. struct {
  140. int retval;
  141. int (*func) (void *, struct pt_regs *);
  142. void * data;
  143. } ipi_action[NR_CPUS];
  144. void ipi_interrupt(int irq, void *unused, struct pt_regs *regs)
  145. {
  146. int cpu = smp_processor_id();
  147. if(!ipi_action[cpu].func)
  148. BUG();
  149. ipi_action[cpu].retval =
  150. ipi_action[cpu].func(ipi_action[cpu].data, regs);
  151. }
  152. /* gdb uses break 4,8 */
  153. #define GDB_BREAK_INSN 0x10004
  154. void handle_gdb_break(struct pt_regs *regs, int wot)
  155. {
  156. struct siginfo si;
  157. si.si_code = wot;
  158. si.si_addr = (void *) (regs->iaoq[0] & ~3);
  159. si.si_signo = SIGTRAP;
  160. si.si_errno = 0;
  161. force_sig_info(SIGTRAP, &si, current);
  162. }
  163. void handle_break(unsigned iir, struct pt_regs *regs)
  164. {
  165. struct siginfo si;
  166. #ifdef CONFIG_KWDB
  167. struct save_state ssp;
  168. #endif /* CONFIG_KWDB */   
  169. flush_all_caches();
  170. switch(iir) {
  171. case 0x00:
  172. /* show registers, halt */
  173. cli();
  174. printk("break 0,0: pid=%d command='%s'n",
  175.        current->pid, current->comm);
  176. die_if_kernel("Breakpoint", regs, 0);
  177. show_regs(regs);
  178. si.si_code = TRAP_BRKPT;
  179. si.si_addr = (void *) (regs->iaoq[0] & ~3);
  180. si.si_signo = SIGTRAP;
  181. force_sig_info(SIGTRAP, &si, current);
  182. break;
  183. case GDB_BREAK_INSN:
  184. die_if_kernel("Breakpoint", regs, 0);
  185. handle_gdb_break(regs, TRAP_BRKPT);
  186. break;
  187. #ifdef CONFIG_KWDB
  188. case KGDB_BREAK_INSN:
  189. mtctl(0, 15);
  190. pt_regs_to_ssp(regs, &ssp);
  191. kgdb_trap(I_BRK_INST, &ssp, 1);
  192. ssp_to_pt_regs(&ssp, regs);
  193. break;
  194. case KGDB_INIT_BREAK_INSN:
  195. mtctl(0, 15);
  196. pt_regs_to_ssp(regs, &ssp);
  197. kgdb_trap(I_BRK_INST, &ssp, 1);
  198. ssp_to_pt_regs(&ssp, regs);
  199. /* Advance pcoq to skip break */
  200. regs->iaoq[0] = regs->iaoq[1];
  201. regs->iaoq[1] += 4;
  202. break;
  203. #endif /* CONFIG_KWDB */
  204. default:
  205. set_eiem(0);
  206. printk("break %#08x: pid=%d command='%s'n",
  207.        iir, current->pid, current->comm);
  208. show_regs(regs);
  209. si.si_signo = SIGTRAP;
  210. si.si_code = TRAP_BRKPT;
  211. si.si_addr = (void *) (regs->iaoq[0] & ~3);
  212. force_sig_info(SIGTRAP, &si, current);
  213. return;
  214. }
  215. }
  216. /* Format of the floating-point exception registers. */
  217. struct exc_reg {
  218. unsigned int exception : 6;
  219. unsigned int ei : 26;
  220. };
  221. /* Macros for grabbing bits of the instruction format from the 'ei'
  222.    field above. */
  223. /* Major opcode 0c and 0e */
  224. #define FP0CE_UID(i) (((i) >> 6) & 3)
  225. #define FP0CE_CLASS(i) (((i) >> 9) & 3)
  226. #define FP0CE_SUBOP(i) (((i) >> 13) & 7)
  227. #define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */
  228. #define FP0C_FORMAT(i) (((i) >> 11) & 3)
  229. #define FP0E_FORMAT(i) (((i) >> 11) & 1)
  230. /* Major opcode 0c, uid 2 (performance monitoring) */
  231. #define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)
  232. /* Major opcode 2e (fused operations).   */
  233. #define FP2E_SUBOP(i)  (((i) >> 5) & 1)
  234. #define FP2E_FORMAT(i) (((i) >> 11) & 1)
  235. /* Major opcode 26 (FMPYSUB) */
  236. /* Major opcode 06 (FMPYADD) */
  237. #define FPx6_FORMAT(i) ((i) & 0x1f)
  238. /* Flags and enable bits of the status word. */
  239. #define FPSW_FLAGS(w) ((w) >> 27)
  240. #define FPSW_ENABLE(w) ((w) & 0x1f)
  241. #define FPSW_V (1<<4)
  242. #define FPSW_Z (1<<3)
  243. #define FPSW_O (1<<2)
  244. #define FPSW_U (1<<1)
  245. #define FPSW_I (1<<0)
  246. /* Emulate a floating point instruction if necessary and possible
  247.    (this will be moved elsewhere eventually).  Return zero if
  248.    successful or if emulation was not required, -1 if the instruction
  249.    is actually illegal or unimplemented.  The status word passed as
  250.    the first parameter will be modified to signal exceptions, if
  251.    any. */
  252. /* FIXME!!!  This is really incomplete and, at the moment, most
  253.    illegal FP instructions will simply act as no-ops.  Obviously that
  254.    is *not* what we want.  Also we don't even try to handle exception
  255.    types other than the 'unimplemented' ones. */
  256. int
  257. fp_emul_insn(u32 *sw, struct exc_reg exc, struct pt_regs *regs)
  258. {
  259. switch (exc.exception) {
  260. case 0x3:  /* Unimplemented, opcode 06 */
  261. break;
  262. case 0x9:  /* Unimplemented, opcode 0c */
  263. /* We do not support quadword operations, end of
  264.                    story.  There's no support for them in GCC. */
  265. if (FP0C_FORMAT(exc.ei) == 3)
  266. return -1; /* SIGILL */
  267. /* Fall through. */
  268. case 0xa:  /* Unimplemented, opcode 0e */
  269. if (FP0CE_CLASS(exc.ei) == 1) {
  270. /* FCNV instructions of various sorts. */
  271. } else {
  272. if (FP0CE_CLASS(exc.ei == 0)
  273.     && FP0CE_SUBOP(exc.ei == 5)) {
  274. /* FRND instructions should be
  275.                                    emulated, at some point, I
  276.                                    guess. */
  277. return -1; /* SIGILL */
  278. }
  279. }
  280. break;
  281. case 0x23: /* Unimplemented, opcode 26 */
  282. break;
  283. case 0x2b: /* Unimplemented, opcode 2e */
  284. break;
  285. case 0x1:  /* Unimplemented, opcode 0e/0c */
  286. /* FIXME: How the hell are we supposed to tell which
  287.                    opcode it is? */
  288. break;
  289. default:
  290. return -1; /* Punt */
  291. }
  292. return 0;
  293. }
  294. /* Handle a floating point exception.  Return zero if the faulting
  295.    instruction can be completed successfully. */
  296. int
  297. handle_fpe(struct pt_regs *regs)
  298. {
  299. struct siginfo si;
  300. union {
  301. struct fpsw {
  302. /* flag bits */
  303. unsigned int fv : 1;
  304. unsigned int fz : 1;
  305. unsigned int fo : 1;
  306. unsigned int fu : 1;
  307. unsigned int fi : 1;
  308. unsigned int c : 1;
  309. unsigned int pad1 : 4;
  310. unsigned int cq : 11;
  311. unsigned int rm : 2;
  312. unsigned int pad2 : 2;
  313. unsigned int t : 1;
  314. unsigned int d : 1;
  315. /* enable bits */
  316. unsigned int ev : 1;
  317. unsigned int ez : 1;
  318. unsigned int eo : 1;
  319. unsigned int eu : 1;
  320. unsigned int ei : 1;
  321. } status;
  322. u32 word;
  323. } sw;
  324. struct exc_reg excepts[7];
  325. unsigned int code = 0;
  326. unsigned int throw;
  327. /* Status word = FR0L. */
  328. memcpy(&sw, regs->fr, sizeof(sw));
  329. /* Exception words = FR0R-FR3R. */
  330. memcpy(excepts, ((char *) regs->fr) + 4, sizeof(excepts));
  331. /* This is all CPU dependent.  Since there is no public
  332.            documentation on the PA2.0 processors we will just assume
  333.            everything is like the 7100/7100LC/7300LC for now.
  334.    Specifically: All exceptions are marked as "unimplemented"
  335.    in the exception word, and the only exception word used is
  336.    excepts[1]. */
  337. /* Try to emulate the instruction.  Also determine if it is
  338.            really an illegal instruction in the process.
  339.    FIXME: fp_emul_insn() only checks for the "unimplemented"
  340.    exceptions at the moment.  So this may break horribly on
  341.    PA2.0, where we may want to also check to see if we should
  342.    just send SIGFPE (or maybe not, let's see the documentation
  343.    first...) */
  344. if (fp_emul_insn(&sw.word, excepts[1], regs) == -1)
  345. goto send_sigill;
  346. /* Take the intersection of the flag bits in the FPSW and the
  347.            enable bits in the FPSW. */
  348. throw = FPSW_FLAGS(sw.word) & FPSW_ENABLE(sw.word);
  349. /* Concoct an appropriate si_code.  Of course we don't know
  350.            what to do if multiple exceptions were enabled and multiple
  351.            flags were set.  Maybe that's why HP/UX doesn't implement
  352.            feenableexcept(). */
  353. if (throw == 0)
  354. goto success; /* Duh. */
  355. else if (throw & FPSW_V)
  356. code = FPE_FLTINV;
  357. else if (throw & FPSW_Z)
  358. code = FPE_FLTDIV;
  359. else if (throw & FPSW_O)
  360. code = FPE_FLTOVF;
  361. else if (throw & FPSW_U)
  362. code = FPE_FLTUND;
  363. else if (throw & FPSW_I)
  364. code = FPE_FLTRES;
  365. #if 1 /* Debugging... */
  366. printk("Unemulated floating point exception, pid=%d (%s)n",
  367.        current->pid, current->comm);
  368. show_regs(regs);
  369. {
  370. int i;
  371. printk("FP Status: %08xn", sw.word);
  372. printk("FP Exceptions:n");
  373. for (i = 0; i < 7; i++) {
  374. printk("tExcept%d: exception %03x insn %06xn",
  375.        i, excepts[i].exception, excepts[i].ei);
  376. }
  377. }
  378. #endif
  379. /* FIXME: Should we clear the flag bits, T bit, and exception
  380.            registers here? */
  381. si.si_signo = SIGFPE;
  382. si.si_errno = 0;
  383. si.si_code = code;
  384. si.si_addr = (void *) regs->iaoq[0];
  385. force_sig_info(SIGFPE, &si, current);
  386. return -1;
  387.  send_sigill:
  388. si.si_signo = SIGILL;
  389. si.si_errno = 0;
  390. si.si_code = ILL_COPROC;
  391. si.si_addr = (void *) regs->iaoq[0];
  392. force_sig_info(SIGILL, &si, current);
  393. return -1;
  394.  success:
  395. /* We absolutely have to clear the T bit and exception
  396.            registers to allow the process to recover.  Otherwise every
  397.            subsequent floating point instruction will trap. */
  398. sw.status.t = 0;
  399. memset(excepts, 0, sizeof(excepts));
  400. memcpy(regs->fr, &sw, sizeof(sw));
  401. memcpy(((char *) regs->fr) + 4,excepts , sizeof(excepts));
  402. return 0;
  403. }
  404. int handle_toc(void)
  405. {
  406. return 0;
  407. }
  408. void default_trap(int code, struct pt_regs *regs)
  409. {
  410. printk("Trap %d on CPU %dn", code, smp_processor_id());
  411. show_regs(regs);
  412. }
  413. void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;
  414. #ifdef CONFIG_KWDB
  415. int
  416. debug_call (void) {
  417.     printk ("Debug call.n");
  418.     return 0;
  419. }
  420. int
  421. debug_call_leaf (void) {
  422.     return 0;
  423. }
  424. #endif /* CONFIG_KWDB */
  425. extern void do_page_fault(struct pt_regs *, int, unsigned long);
  426. extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long);
  427. extern void transfer_pim_to_trap_frame(struct pt_regs *);
  428. extern void pdc_console_restart(void);
  429. void handle_interruption(int code, struct pt_regs *regs)
  430. {
  431. unsigned long fault_address = 0;
  432. unsigned long fault_space = 0;
  433. struct siginfo si;
  434. #ifdef CONFIG_KWDB
  435. struct save_state ssp;
  436. #endif /* CONFIG_KWDB */   
  437. if (code == 1)
  438.     pdc_console_restart();  /* switch back to pdc if HPMC */
  439. else
  440.     sti();
  441. #ifdef __LP64__
  442. /*
  443.  * FIXME:
  444.  * For 32 bit processes we don't want the b bits (bits 0 & 1)
  445.  * in the ior. This is more appropriately handled in the tlb
  446.  * miss handlers. Changes need to be made to support addresses
  447.  * >32 bits for 64 bit processes.
  448.  */
  449. regs->ior &= 0x3FFFFFFFFFFFFFFFUL;
  450. #endif
  451. #if 0
  452. printk("interrupted with code %d, regs %pn", code, regs);
  453. show_regs(regs);
  454. #endif
  455. switch(code) {
  456. case  1:
  457. parisc_terminate("High Priority Machine Check (HPMC)",regs,code,0);
  458. /* NOT REACHED */
  459. case  3: /* Recovery counter trap */
  460. regs->gr[0] &= ~PSW_R;
  461. if (regs->iasq[0])
  462. handle_gdb_break(regs, TRAP_TRACE);
  463. /* else this must be the start of a syscall - just let it
  464.  * run.
  465.  */
  466. return;
  467. case  5:
  468. flush_all_caches();
  469. cpu_lpmc(5, regs);
  470. return;
  471. case  6:
  472. fault_address = regs->iaoq[0];
  473. fault_space   = regs->iasq[0];
  474. break;
  475. case  9: /* Break Instruction */
  476. handle_break(regs->iir,regs);
  477. return;
  478. case 14:
  479. /* Assist Exception Trap, i.e. floating point exception. */
  480. die_if_kernel("Floating point exception", regs, 0); /* quiet */
  481. handle_fpe(regs);
  482. return;
  483. case 15:
  484. case 16:  /* Non-Access TLB miss faulting address is in IOR */
  485. case 17:
  486. case 26:
  487. fault_address = regs->ior;
  488. fault_space   = regs->isr;
  489. if (code == 26 && fault_space == 0)
  490.     parisc_terminate("Data access rights fault in kernel",regs,code,fault_address);
  491. break;
  492. case 19:
  493. regs->gr[0] |= PSW_X; /* So we can single-step over the trap */
  494. /* fall thru */
  495. case 21:
  496. handle_gdb_break(regs, TRAP_HWBKPT);
  497. return;
  498. case 25: /* Taken branch trap */
  499. regs->gr[0] &= ~PSW_T;
  500. if (regs->iasq[0])
  501. handle_gdb_break(regs, TRAP_BRANCH);
  502. /* else this must be the start of a syscall - just let it
  503.  * run.
  504.  */
  505. return;
  506. #if 0 /* def CONFIG_KWDB */
  507. case I_TAKEN_BR: /* 25 */
  508. mtctl(0, 15);
  509. pt_regs_to_ssp(regs, &ssp);
  510. kgdb_trap(I_TAKEN_BR, &ssp, 1);
  511. ssp_to_pt_regs(&ssp, regs);
  512. break;
  513. #endif /* CONFIG_KWDB */
  514. case  8:
  515. die_if_kernel("Illegal instruction", regs, code);
  516. si.si_code = ILL_ILLOPC;
  517. goto give_sigill;
  518. case 10:
  519. die_if_kernel("Priviledged operation - shouldn't happen!", regs, code);
  520. si.si_code = ILL_PRVOPC;
  521. goto give_sigill;
  522. case 11:
  523. die_if_kernel("Priviledged register - shouldn't happen!", regs, code);
  524. si.si_code = ILL_PRVREG;
  525. give_sigill:
  526. si.si_signo = SIGILL;
  527. si.si_errno = 0;
  528. si.si_addr = (void *) regs->iaoq[0];
  529. force_sig_info(SIGILL, &si, current);
  530. return;
  531. case 28:  /* Unaligned just causes SIGBUS for now */
  532. die_if_kernel("Unaligned data reference", regs, code);
  533. si.si_code = BUS_ADRALN;
  534. si.si_signo = SIGBUS;
  535. si.si_errno = 0;
  536. si.si_addr = (void *) regs->ior;
  537. force_sig_info(SIGBUS, &si, current);
  538. return;
  539. default:
  540. if (user_mode(regs)) {
  541. printk("nhandle_interruption() pid=%d command='%s'n",
  542.     current->pid, current->comm);
  543. show_regs(regs);
  544. /* SIGBUS, for lack of a better one. */
  545. si.si_signo = SIGBUS;
  546. si.si_code = BUS_OBJERR;
  547. si.si_errno = 0;
  548. si.si_addr = (void *) regs->ior;
  549. force_sig_info(SIGBUS, &si, current);
  550. return;
  551. }
  552. parisc_terminate("Unexpected Interruption!",regs,code,0);
  553. /* NOT REACHED */
  554. }
  555. if (user_mode(regs)) {
  556.     if (fault_space != regs->sr[7]) {
  557. if (fault_space == 0)
  558. printk("User Fault on Kernel Space ");
  559. else /* this case should never happen, but whatever... */
  560. printk("User Fault (long pointer) ");
  561. printk("pid=%d command='%s'n", current->pid, current->comm);
  562. show_regs(regs);
  563. si.si_signo = SIGSEGV;
  564. si.si_errno = 0;
  565. si.si_code = SEGV_MAPERR;
  566. si.si_addr = (void *) regs->ior;
  567. force_sig_info(SIGSEGV, &si, current);
  568. return;
  569.     }
  570. }
  571. else {
  572.     /*
  573.      * The kernel should never fault on its own address space.
  574.      */
  575.     if (fault_space == 0)
  576.     parisc_terminate("Kernel Fault",regs,code,fault_address);
  577. }
  578. #ifdef CONFIG_KWDB
  579. debug_call_leaf ();
  580. #endif /* CONFIG_KWDB */
  581. do_page_fault(regs, code, fault_address);
  582. /*
  583.  * This should not be necessary.
  584.  * However, we do not currently
  585.  * implement flush_page_to_ram.
  586.  *
  587.  * The problem is that if we just
  588.  * brought in some code through the
  589.  * D-cache, the I-cache may not see
  590.  * it since it hasn't been flushed
  591.  * to ram.
  592.  */
  593. /*  flush_all_caches(); */
  594. #if 0
  595. printk("returning %pn", regs);
  596. /* show_regs(regs); */
  597. #endif
  598. return;
  599. }
  600. void show_stack(unsigned long sp)
  601. {
  602. #if 1
  603. if ((sp & 0xc0000000UL) == 0xc0000000UL) {
  604.     __u32 *stackptr;
  605.     __u32 *dumpptr;
  606.     /* Stack Dump! */
  607.     stackptr = (__u32 *)sp;
  608.     dumpptr  = (__u32 *)(sp & ~(INIT_TASK_SIZE - 1));
  609.     printk("nDumping Stack from %p to %p:n",dumpptr,stackptr);
  610.     while (dumpptr < stackptr) {
  611. printk("%04x %08x %08x %08x %08x %08x %08x %08x %08xn",
  612.     ((__u32)dumpptr) & 0xffff,
  613.     dumpptr[0], dumpptr[1], dumpptr[2], dumpptr[3],
  614.     dumpptr[4], dumpptr[5], dumpptr[6], dumpptr[7]);
  615. dumpptr += 8;
  616.     }
  617. }
  618. #endif
  619. }
  620. void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset)
  621. {
  622. set_eiem(0);
  623. cli();
  624. if (code == 1)
  625.     transfer_pim_to_trap_frame(regs);
  626. #if 1
  627. show_stack(regs->gr[30]);
  628. #endif
  629. printk("n%s: Code=%d regs=%p (Addr=%08lx)n",msg,code,regs,offset);
  630. show_regs(regs);
  631. for(;;)
  632.     ;
  633. }
  634. void transfer_pim_to_trap_frame(struct pt_regs *regs)
  635. {
  636.     register int i;
  637.     extern unsigned int hpmc_pim_data[];
  638.     struct pdc_hpmc_pim_11 *pim_narrow;
  639.     struct pdc_hpmc_pim_20 *pim_wide;
  640.     if (boot_cpu_data.cpu_type >= pcxu) {
  641. pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;
  642. /*
  643.  * Note: The following code will probably generate a
  644.  * bunch of truncation error warnings from the compiler.
  645.  * Could be handled with an ifdef, but perhaps there
  646.  * is a better way.
  647.  */
  648. regs->gr[0] = pim_wide->cr[22];
  649. for (i = 1; i < 32; i++)
  650.     regs->gr[i] = pim_wide->gr[i];
  651. for (i = 0; i < 32; i++)
  652.     regs->fr[i] = pim_wide->fr[i];
  653. for (i = 0; i < 8; i++)
  654.     regs->sr[i] = pim_wide->sr[i];
  655. regs->iasq[0] = pim_wide->cr[17];
  656. regs->iasq[1] = pim_wide->iasq_back;
  657. regs->iaoq[0] = pim_wide->cr[18];
  658. regs->iaoq[1] = pim_wide->iaoq_back;
  659. regs->cr30 = pim_wide->cr[30];
  660. regs->sar  = pim_wide->cr[11];
  661. regs->iir  = pim_wide->cr[19];
  662. regs->isr  = pim_wide->cr[20];
  663. regs->ior  = pim_wide->cr[21];
  664.     }
  665.     else {
  666. pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;
  667. regs->gr[0] = pim_narrow->cr[22];
  668. for (i = 1; i < 32; i++)
  669.     regs->gr[i] = pim_narrow->gr[i];
  670. for (i = 0; i < 32; i++)
  671.     regs->fr[i] = pim_narrow->fr[i];
  672. for (i = 0; i < 8; i++)
  673.     regs->sr[i] = pim_narrow->sr[i];
  674. regs->iasq[0] = pim_narrow->cr[17];
  675. regs->iasq[1] = pim_narrow->iasq_back;
  676. regs->iaoq[0] = pim_narrow->cr[18];
  677. regs->iaoq[1] = pim_narrow->iaoq_back;
  678. regs->cr30 = pim_narrow->cr[30];
  679. regs->sar  = pim_narrow->cr[11];
  680. regs->iir  = pim_narrow->cr[19];
  681. regs->isr  = pim_narrow->cr[20];
  682. regs->ior  = pim_narrow->cr[21];
  683.     }
  684.     /*
  685.      * The following fields only have meaning if we came through
  686.      * another path. So just zero them here.
  687.      */
  688.     regs->ksp = 0;
  689.     regs->kpc = 0;
  690.     regs->orig_r28 = 0;
  691. }
  692. int __init check_ivt(void *iva)
  693. {
  694. int i;
  695. u32 check = 0;
  696. u32 *ivap;
  697. u32 *hpmcp;
  698. u32 length;
  699. extern void os_hpmc(void);
  700. extern void os_hpmc_end(void);
  701. if(strcmp((char *)iva, "cows can fly"))
  702. return -1;
  703. ivap = (u32 *)iva;
  704. for (i = 0; i < 8; i++)
  705.     *ivap++ = 0;
  706. /* Compute Checksum for HPMC handler */
  707. length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc);
  708. ivap[7] = length;
  709. hpmcp = (u32 *)os_hpmc;
  710. for(i=0; i<length/4; i++)
  711.     check += *hpmcp++;
  712. for(i=0; i<8; i++)
  713.     check += ivap[i];
  714. ivap[5] = -check;
  715. return 0;
  716. }
  717. #ifndef __LP64__
  718. extern const void fault_vector_11;
  719. #endif
  720. extern const void fault_vector_20;
  721. void __init trap_init(void)
  722. {
  723. volatile long eiem;
  724. void *iva;
  725. printk("trap_initn");
  726. if (boot_cpu_data.cpu_type >= pcxu)
  727. iva = (void *) &fault_vector_20;
  728. else
  729. #ifdef __LP64__
  730. panic("Can't boot 64-bit OS on PA1.1 processor!");
  731. #else
  732. iva = (void *) &fault_vector_11;
  733. #endif
  734. if(check_ivt(iva))
  735. panic("IVT invalid");
  736. mtctl(0, 30);
  737. mtctl(90000000, 16);
  738. set_eiem(-1L);
  739. mtctl(-1L, 23);
  740. asm volatile ("rsm 0,%0" : "=r" (eiem));
  741. }