PageRenderTime 67ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/arch/openrisc/kernel/traps.c

https://github.com/gby/linux
C | 540 lines | 414 code | 82 blank | 44 comment | 53 complexity | 2131711e1b9da71575a1633be0f2892a MD5 | raw file
  1. /*
  2. * OpenRISC traps.c
  3. *
  4. * Linux architectural port borrowing liberally from similar works of
  5. * others. All original copyrights apply as per the original source
  6. * declaration.
  7. *
  8. * Modifications for the OpenRISC architecture:
  9. * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
  10. * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License
  14. * as published by the Free Software Foundation; either version
  15. * 2 of the License, or (at your option) any later version.
  16. *
  17. * Here we handle the break vectors not used by the system call
  18. * mechanism, as well as some general stack/register dumping
  19. * things.
  20. *
  21. */
  22. #include <linux/init.h>
  23. #include <linux/sched.h>
  24. #include <linux/sched/debug.h>
  25. #include <linux/sched/task_stack.h>
  26. #include <linux/kernel.h>
  27. #include <linux/extable.h>
  28. #include <linux/kmod.h>
  29. #include <linux/string.h>
  30. #include <linux/errno.h>
  31. #include <linux/ptrace.h>
  32. #include <linux/timer.h>
  33. #include <linux/mm.h>
  34. #include <linux/kallsyms.h>
  35. #include <linux/uaccess.h>
  36. #include <asm/segment.h>
  37. #include <asm/io.h>
  38. #include <asm/pgtable.h>
  39. extern char _etext, _stext;
  40. int kstack_depth_to_print = 0x180;
  41. int lwa_flag;
  42. unsigned long __user *lwa_addr;
  43. static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
  44. {
  45. return p > (void *)tinfo && p < (void *)tinfo + THREAD_SIZE - 3;
  46. }
  47. void show_trace(struct task_struct *task, unsigned long *stack)
  48. {
  49. struct thread_info *context;
  50. unsigned long addr;
  51. context = (struct thread_info *)
  52. ((unsigned long)stack & (~(THREAD_SIZE - 1)));
  53. while (valid_stack_ptr(context, stack)) {
  54. addr = *stack++;
  55. if (__kernel_text_address(addr)) {
  56. printk(" [<%08lx>]", addr);
  57. print_symbol(" %s", addr);
  58. printk("\n");
  59. }
  60. }
  61. printk(" =======================\n");
  62. }
  63. /* displays a short stack trace */
  64. void show_stack(struct task_struct *task, unsigned long *esp)
  65. {
  66. unsigned long addr, *stack;
  67. int i;
  68. if (esp == NULL)
  69. esp = (unsigned long *)&esp;
  70. stack = esp;
  71. printk("Stack dump [0x%08lx]:\n", (unsigned long)esp);
  72. for (i = 0; i < kstack_depth_to_print; i++) {
  73. if (kstack_end(stack))
  74. break;
  75. if (__get_user(addr, stack)) {
  76. /* This message matches "failing address" marked
  77. s390 in ksymoops, so lines containing it will
  78. not be filtered out by ksymoops. */
  79. printk("Failing address 0x%lx\n", (unsigned long)stack);
  80. break;
  81. }
  82. stack++;
  83. printk("sp + %02d: 0x%08lx\n", i * 4, addr);
  84. }
  85. printk("\n");
  86. show_trace(task, esp);
  87. return;
  88. }
  89. void show_trace_task(struct task_struct *tsk)
  90. {
  91. /*
  92. * TODO: SysRq-T trace dump...
  93. */
  94. }
  95. void show_registers(struct pt_regs *regs)
  96. {
  97. int i;
  98. int in_kernel = 1;
  99. unsigned long esp;
  100. esp = (unsigned long)(&regs->sp);
  101. if (user_mode(regs))
  102. in_kernel = 0;
  103. printk("CPU #: %d\n"
  104. " PC: %08lx SR: %08lx SP: %08lx\n",
  105. smp_processor_id(), regs->pc, regs->sr, regs->sp);
  106. printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
  107. 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
  108. printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
  109. regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
  110. printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
  111. regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
  112. printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
  113. regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
  114. printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
  115. regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
  116. printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
  117. regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
  118. printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
  119. regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
  120. printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
  121. regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
  122. printk(" RES: %08lx oGPR11: %08lx\n",
  123. regs->gpr[11], regs->orig_gpr11);
  124. printk("Process %s (pid: %d, stackpage=%08lx)\n",
  125. current->comm, current->pid, (unsigned long)current);
  126. /*
  127. * When in-kernel, we also print out the stack and code at the
  128. * time of the fault..
  129. */
  130. if (in_kernel) {
  131. printk("\nStack: ");
  132. show_stack(NULL, (unsigned long *)esp);
  133. printk("\nCode: ");
  134. if (regs->pc < PAGE_OFFSET)
  135. goto bad;
  136. for (i = -24; i < 24; i++) {
  137. unsigned char c;
  138. if (__get_user(c, &((unsigned char *)regs->pc)[i])) {
  139. bad:
  140. printk(" Bad PC value.");
  141. break;
  142. }
  143. if (i == 0)
  144. printk("(%02x) ", c);
  145. else
  146. printk("%02x ", c);
  147. }
  148. }
  149. printk("\n");
  150. }
  151. void nommu_dump_state(struct pt_regs *regs,
  152. unsigned long ea, unsigned long vector)
  153. {
  154. int i;
  155. unsigned long addr, stack = regs->sp;
  156. printk("\n\r[nommu_dump_state] :: ea %lx, vector %lx\n\r", ea, vector);
  157. printk("CPU #: %d\n"
  158. " PC: %08lx SR: %08lx SP: %08lx\n",
  159. 0, regs->pc, regs->sr, regs->sp);
  160. printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
  161. 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
  162. printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
  163. regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
  164. printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
  165. regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
  166. printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
  167. regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
  168. printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
  169. regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
  170. printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
  171. regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
  172. printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
  173. regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
  174. printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
  175. regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
  176. printk(" RES: %08lx oGPR11: %08lx\n",
  177. regs->gpr[11], regs->orig_gpr11);
  178. printk("Process %s (pid: %d, stackpage=%08lx)\n",
  179. ((struct task_struct *)(__pa(current)))->comm,
  180. ((struct task_struct *)(__pa(current)))->pid,
  181. (unsigned long)current);
  182. printk("\nStack: ");
  183. printk("Stack dump [0x%08lx]:\n", (unsigned long)stack);
  184. for (i = 0; i < kstack_depth_to_print; i++) {
  185. if (((long)stack & (THREAD_SIZE - 1)) == 0)
  186. break;
  187. stack++;
  188. printk("%lx :: sp + %02d: 0x%08lx\n", stack, i * 4,
  189. *((unsigned long *)(__pa(stack))));
  190. }
  191. printk("\n");
  192. printk("Call Trace: ");
  193. i = 1;
  194. while (((long)stack & (THREAD_SIZE - 1)) != 0) {
  195. addr = *((unsigned long *)__pa(stack));
  196. stack++;
  197. if (kernel_text_address(addr)) {
  198. if (i && ((i % 6) == 0))
  199. printk("\n ");
  200. printk(" [<%08lx>]", addr);
  201. i++;
  202. }
  203. }
  204. printk("\n");
  205. printk("\nCode: ");
  206. for (i = -24; i < 24; i++) {
  207. unsigned char c;
  208. c = ((unsigned char *)(__pa(regs->pc)))[i];
  209. if (i == 0)
  210. printk("(%02x) ", c);
  211. else
  212. printk("%02x ", c);
  213. }
  214. printk("\n");
  215. }
  216. /* This is normally the 'Oops' routine */
  217. void die(const char *str, struct pt_regs *regs, long err)
  218. {
  219. console_verbose();
  220. printk("\n%s#: %04lx\n", str, err & 0xffff);
  221. show_registers(regs);
  222. #ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
  223. printk("\n\nUNHANDLED_EXCEPTION: entering infinite loop\n");
  224. /* shut down interrupts */
  225. local_irq_disable();
  226. __asm__ __volatile__("l.nop 1");
  227. do {} while (1);
  228. #endif
  229. do_exit(SIGSEGV);
  230. }
  231. /* This is normally the 'Oops' routine */
  232. void die_if_kernel(const char *str, struct pt_regs *regs, long err)
  233. {
  234. if (user_mode(regs))
  235. return;
  236. die(str, regs, err);
  237. }
  238. void unhandled_exception(struct pt_regs *regs, int ea, int vector)
  239. {
  240. printk("Unable to handle exception at EA =0x%x, vector 0x%x",
  241. ea, vector);
  242. die("Oops", regs, 9);
  243. }
  244. void __init trap_init(void)
  245. {
  246. /* Nothing needs to be done */
  247. }
  248. asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
  249. {
  250. siginfo_t info;
  251. memset(&info, 0, sizeof(info));
  252. info.si_signo = SIGTRAP;
  253. info.si_code = TRAP_TRACE;
  254. info.si_addr = (void *)address;
  255. force_sig_info(SIGTRAP, &info, current);
  256. regs->pc += 4;
  257. }
  258. asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
  259. {
  260. siginfo_t info;
  261. if (user_mode(regs)) {
  262. /* Send a SIGSEGV */
  263. info.si_signo = SIGSEGV;
  264. info.si_errno = 0;
  265. /* info.si_code has been set above */
  266. info.si_addr = (void *)address;
  267. force_sig_info(SIGSEGV, &info, current);
  268. } else {
  269. printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
  270. show_registers(regs);
  271. die("Die:", regs, address);
  272. }
  273. }
  274. asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address)
  275. {
  276. siginfo_t info;
  277. if (user_mode(regs)) {
  278. /* Send a SIGBUS */
  279. info.si_signo = SIGBUS;
  280. info.si_errno = 0;
  281. info.si_code = BUS_ADRERR;
  282. info.si_addr = (void *)address;
  283. force_sig_info(SIGBUS, &info, current);
  284. } else { /* Kernel mode */
  285. printk("KERNEL: Bus error (SIGBUS) 0x%.8lx\n", address);
  286. show_registers(regs);
  287. die("Die:", regs, address);
  288. }
  289. }
  290. static inline int in_delay_slot(struct pt_regs *regs)
  291. {
  292. #ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX
  293. /* No delay slot flag, do the old way */
  294. unsigned int op, insn;
  295. insn = *((unsigned int *)regs->pc);
  296. op = insn >> 26;
  297. switch (op) {
  298. case 0x00: /* l.j */
  299. case 0x01: /* l.jal */
  300. case 0x03: /* l.bnf */
  301. case 0x04: /* l.bf */
  302. case 0x11: /* l.jr */
  303. case 0x12: /* l.jalr */
  304. return 1;
  305. default:
  306. return 0;
  307. }
  308. #else
  309. return regs->sr & SPR_SR_DSX;
  310. #endif
  311. }
  312. static inline void adjust_pc(struct pt_regs *regs, unsigned long address)
  313. {
  314. int displacement;
  315. unsigned int rb, op, jmp;
  316. if (unlikely(in_delay_slot(regs))) {
  317. /* In delay slot, instruction at pc is a branch, simulate it */
  318. jmp = *((unsigned int *)regs->pc);
  319. displacement = sign_extend32(((jmp) & 0x3ffffff) << 2, 27);
  320. rb = (jmp & 0x0000ffff) >> 11;
  321. op = jmp >> 26;
  322. switch (op) {
  323. case 0x00: /* l.j */
  324. regs->pc += displacement;
  325. return;
  326. case 0x01: /* l.jal */
  327. regs->pc += displacement;
  328. regs->gpr[9] = regs->pc + 8;
  329. return;
  330. case 0x03: /* l.bnf */
  331. if (regs->sr & SPR_SR_F)
  332. regs->pc += 8;
  333. else
  334. regs->pc += displacement;
  335. return;
  336. case 0x04: /* l.bf */
  337. if (regs->sr & SPR_SR_F)
  338. regs->pc += displacement;
  339. else
  340. regs->pc += 8;
  341. return;
  342. case 0x11: /* l.jr */
  343. regs->pc = regs->gpr[rb];
  344. return;
  345. case 0x12: /* l.jalr */
  346. regs->pc = regs->gpr[rb];
  347. regs->gpr[9] = regs->pc + 8;
  348. return;
  349. default:
  350. break;
  351. }
  352. } else {
  353. regs->pc += 4;
  354. }
  355. }
  356. static inline void simulate_lwa(struct pt_regs *regs, unsigned long address,
  357. unsigned int insn)
  358. {
  359. unsigned int ra, rd;
  360. unsigned long value;
  361. unsigned long orig_pc;
  362. long imm;
  363. const struct exception_table_entry *entry;
  364. orig_pc = regs->pc;
  365. adjust_pc(regs, address);
  366. ra = (insn >> 16) & 0x1f;
  367. rd = (insn >> 21) & 0x1f;
  368. imm = (short)insn;
  369. lwa_addr = (unsigned long __user *)(regs->gpr[ra] + imm);
  370. if ((unsigned long)lwa_addr & 0x3) {
  371. do_unaligned_access(regs, address);
  372. return;
  373. }
  374. if (get_user(value, lwa_addr)) {
  375. if (user_mode(regs)) {
  376. force_sig(SIGSEGV, current);
  377. return;
  378. }
  379. if ((entry = search_exception_tables(orig_pc))) {
  380. regs->pc = entry->fixup;
  381. return;
  382. }
  383. /* kernel access in kernel space, load it directly */
  384. value = *((unsigned long *)lwa_addr);
  385. }
  386. lwa_flag = 1;
  387. regs->gpr[rd] = value;
  388. }
  389. static inline void simulate_swa(struct pt_regs *regs, unsigned long address,
  390. unsigned int insn)
  391. {
  392. unsigned long __user *vaddr;
  393. unsigned long orig_pc;
  394. unsigned int ra, rb;
  395. long imm;
  396. const struct exception_table_entry *entry;
  397. orig_pc = regs->pc;
  398. adjust_pc(regs, address);
  399. ra = (insn >> 16) & 0x1f;
  400. rb = (insn >> 11) & 0x1f;
  401. imm = (short)(((insn & 0x2200000) >> 10) | (insn & 0x7ff));
  402. vaddr = (unsigned long __user *)(regs->gpr[ra] + imm);
  403. if (!lwa_flag || vaddr != lwa_addr) {
  404. regs->sr &= ~SPR_SR_F;
  405. return;
  406. }
  407. if ((unsigned long)vaddr & 0x3) {
  408. do_unaligned_access(regs, address);
  409. return;
  410. }
  411. if (put_user(regs->gpr[rb], vaddr)) {
  412. if (user_mode(regs)) {
  413. force_sig(SIGSEGV, current);
  414. return;
  415. }
  416. if ((entry = search_exception_tables(orig_pc))) {
  417. regs->pc = entry->fixup;
  418. return;
  419. }
  420. /* kernel access in kernel space, store it directly */
  421. *((unsigned long *)vaddr) = regs->gpr[rb];
  422. }
  423. lwa_flag = 0;
  424. regs->sr |= SPR_SR_F;
  425. }
  426. #define INSN_LWA 0x1b
  427. #define INSN_SWA 0x33
  428. asmlinkage void do_illegal_instruction(struct pt_regs *regs,
  429. unsigned long address)
  430. {
  431. siginfo_t info;
  432. unsigned int op;
  433. unsigned int insn = *((unsigned int *)address);
  434. op = insn >> 26;
  435. switch (op) {
  436. case INSN_LWA:
  437. simulate_lwa(regs, address, insn);
  438. return;
  439. case INSN_SWA:
  440. simulate_swa(regs, address, insn);
  441. return;
  442. default:
  443. break;
  444. }
  445. if (user_mode(regs)) {
  446. /* Send a SIGILL */
  447. info.si_signo = SIGILL;
  448. info.si_errno = 0;
  449. info.si_code = ILL_ILLOPC;
  450. info.si_addr = (void *)address;
  451. force_sig_info(SIGBUS, &info, current);
  452. } else { /* Kernel mode */
  453. printk("KERNEL: Illegal instruction (SIGILL) 0x%.8lx\n",
  454. address);
  455. show_registers(regs);
  456. die("Die:", regs, address);
  457. }
  458. }