traps.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. /*
  2. * arch/s390/kernel/traps.c
  3. *
  4. * S390 version
  5. * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6. * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  7. * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  8. *
  9. * Derived from "arch/i386/kernel/traps.c"
  10. * Copyright (C) 1991, 1992 Linus Torvalds
  11. */
  12. /*
  13. * 'Traps.c' handles hardware traps and faults after we have saved some
  14. * state in 'asm.s'.
  15. */
  16. #include <linux/sched.h>
  17. #include <linux/kernel.h>
  18. #include <linux/string.h>
  19. #include <linux/errno.h>
  20. #include <linux/ptrace.h>
  21. #include <linux/timer.h>
  22. #include <linux/mm.h>
  23. #include <linux/smp.h>
  24. #include <linux/init.h>
  25. #include <linux/interrupt.h>
  26. #include <linux/delay.h>
  27. #include <linux/module.h>
  28. #include <linux/kdebug.h>
  29. #include <linux/kallsyms.h>
  30. #include <linux/reboot.h>
  31. #include <linux/kprobes.h>
  32. #include <linux/bug.h>
  33. #include <linux/utsname.h>
  34. #include <asm/system.h>
  35. #include <asm/uaccess.h>
  36. #include <asm/io.h>
  37. #include <asm/atomic.h>
  38. #include <asm/mathemu.h>
  39. #include <asm/cpcmd.h>
  40. #include <asm/s390_ext.h>
  41. #include <asm/lowcore.h>
  42. #include <asm/debug.h>
  43. /* Called from entry.S only */
  44. extern void handle_per_exception(struct pt_regs *regs);
  45. typedef void pgm_check_handler_t(struct pt_regs *, long);
  46. pgm_check_handler_t *pgm_check_table[128];
  47. #ifdef CONFIG_SYSCTL
  48. #ifdef CONFIG_PROCESS_DEBUG
  49. int sysctl_userprocess_debug = 1;
  50. #else
  51. int sysctl_userprocess_debug = 0;
  52. #endif
  53. #endif
  54. extern pgm_check_handler_t do_protection_exception;
  55. extern pgm_check_handler_t do_dat_exception;
  56. extern pgm_check_handler_t do_monitor_call;
  57. #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
  58. #ifndef CONFIG_64BIT
  59. #define FOURLONG "%08lx %08lx %08lx %08lx\n"
  60. static int kstack_depth_to_print = 12;
  61. #else /* CONFIG_64BIT */
  62. #define FOURLONG "%016lx %016lx %016lx %016lx\n"
  63. static int kstack_depth_to_print = 20;
  64. #endif /* CONFIG_64BIT */
  65. /*
  66. * For show_trace we have tree different stack to consider:
  67. * - the panic stack which is used if the kernel stack has overflown
  68. * - the asynchronous interrupt stack (cpu related)
  69. * - the synchronous kernel stack (process related)
  70. * The stack trace can start at any of the three stack and can potentially
  71. * touch all of them. The order is: panic stack, async stack, sync stack.
  72. */
  73. static unsigned long
  74. __show_trace(unsigned long sp, unsigned long low, unsigned long high)
  75. {
  76. struct stack_frame *sf;
  77. struct pt_regs *regs;
  78. while (1) {
  79. sp = sp & PSW_ADDR_INSN;
  80. if (sp < low || sp > high - sizeof(*sf))
  81. return sp;
  82. sf = (struct stack_frame *) sp;
  83. printk("([<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
  84. print_symbol("%s)\n", sf->gprs[8] & PSW_ADDR_INSN);
  85. /* Follow the backchain. */
  86. while (1) {
  87. low = sp;
  88. sp = sf->back_chain & PSW_ADDR_INSN;
  89. if (!sp)
  90. break;
  91. if (sp <= low || sp > high - sizeof(*sf))
  92. return sp;
  93. sf = (struct stack_frame *) sp;
  94. printk(" [<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
  95. print_symbol("%s\n", sf->gprs[8] & PSW_ADDR_INSN);
  96. }
  97. /* Zero backchain detected, check for interrupt frame. */
  98. sp = (unsigned long) (sf + 1);
  99. if (sp <= low || sp > high - sizeof(*regs))
  100. return sp;
  101. regs = (struct pt_regs *) sp;
  102. printk(" [<%016lx>] ", regs->psw.addr & PSW_ADDR_INSN);
  103. print_symbol("%s\n", regs->psw.addr & PSW_ADDR_INSN);
  104. low = sp;
  105. sp = regs->gprs[15];
  106. }
  107. }
  108. void show_trace(struct task_struct *task, unsigned long *stack)
  109. {
  110. register unsigned long __r15 asm ("15");
  111. unsigned long sp;
  112. sp = (unsigned long) stack;
  113. if (!sp)
  114. sp = task ? task->thread.ksp : __r15;
  115. printk("Call Trace:\n");
  116. #ifdef CONFIG_CHECK_STACK
  117. sp = __show_trace(sp, S390_lowcore.panic_stack - 4096,
  118. S390_lowcore.panic_stack);
  119. #endif
  120. sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE,
  121. S390_lowcore.async_stack);
  122. if (task)
  123. __show_trace(sp, (unsigned long) task_stack_page(task),
  124. (unsigned long) task_stack_page(task) + THREAD_SIZE);
  125. else
  126. __show_trace(sp, S390_lowcore.thread_info,
  127. S390_lowcore.thread_info + THREAD_SIZE);
  128. printk("\n");
  129. if (!task)
  130. task = current;
  131. debug_show_held_locks(task);
  132. }
  133. void show_stack(struct task_struct *task, unsigned long *sp)
  134. {
  135. register unsigned long * __r15 asm ("15");
  136. unsigned long *stack;
  137. int i;
  138. if (!sp)
  139. stack = task ? (unsigned long *) task->thread.ksp : __r15;
  140. else
  141. stack = sp;
  142. for (i = 0; i < kstack_depth_to_print; i++) {
  143. if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
  144. break;
  145. if (i && ((i * sizeof (long) % 32) == 0))
  146. printk("\n ");
  147. printk("%p ", (void *)*stack++);
  148. }
  149. printk("\n");
  150. show_trace(task, sp);
  151. }
  152. /*
  153. * The architecture-independent dump_stack generator
  154. */
  155. void dump_stack(void)
  156. {
  157. printk("CPU: %d %s %s %.*s\n",
  158. task_thread_info(current)->cpu, print_tainted(),
  159. init_utsname()->release,
  160. (int)strcspn(init_utsname()->version, " "),
  161. init_utsname()->version);
  162. printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
  163. current->comm, current->pid, current,
  164. (void *) current->thread.ksp);
  165. show_stack(NULL, NULL);
  166. }
  167. EXPORT_SYMBOL(dump_stack);
  168. static inline int mask_bits(struct pt_regs *regs, unsigned long bits)
  169. {
  170. return (regs->psw.mask & bits) / ((~bits + 1) & bits);
  171. }
  172. void show_registers(struct pt_regs *regs)
  173. {
  174. char *mode;
  175. mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl";
  176. printk("%s PSW : %p %p",
  177. mode, (void *) regs->psw.mask,
  178. (void *) regs->psw.addr);
  179. print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN);
  180. printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
  181. "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
  182. mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
  183. mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY),
  184. mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT),
  185. mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
  186. mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
  187. #ifdef CONFIG_64BIT
  188. printk(" EA:%x", mask_bits(regs, PSW_BASE_BITS));
  189. #endif
  190. printk("\n%s GPRS: " FOURLONG, mode,
  191. regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
  192. printk(" " FOURLONG,
  193. regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
  194. printk(" " FOURLONG,
  195. regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
  196. printk(" " FOURLONG,
  197. regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
  198. show_code(regs);
  199. }
  200. /* This is called from fs/proc/array.c */
  201. char *task_show_regs(struct task_struct *task, char *buffer)
  202. {
  203. struct pt_regs *regs;
  204. regs = task_pt_regs(task);
  205. buffer += sprintf(buffer, "task: %p, ksp: %p\n",
  206. task, (void *)task->thread.ksp);
  207. buffer += sprintf(buffer, "User PSW : %p %p\n",
  208. (void *) regs->psw.mask, (void *)regs->psw.addr);
  209. buffer += sprintf(buffer, "User GPRS: " FOURLONG,
  210. regs->gprs[0], regs->gprs[1],
  211. regs->gprs[2], regs->gprs[3]);
  212. buffer += sprintf(buffer, " " FOURLONG,
  213. regs->gprs[4], regs->gprs[5],
  214. regs->gprs[6], regs->gprs[7]);
  215. buffer += sprintf(buffer, " " FOURLONG,
  216. regs->gprs[8], regs->gprs[9],
  217. regs->gprs[10], regs->gprs[11]);
  218. buffer += sprintf(buffer, " " FOURLONG,
  219. regs->gprs[12], regs->gprs[13],
  220. regs->gprs[14], regs->gprs[15]);
  221. buffer += sprintf(buffer, "User ACRS: %08x %08x %08x %08x\n",
  222. task->thread.acrs[0], task->thread.acrs[1],
  223. task->thread.acrs[2], task->thread.acrs[3]);
  224. buffer += sprintf(buffer, " %08x %08x %08x %08x\n",
  225. task->thread.acrs[4], task->thread.acrs[5],
  226. task->thread.acrs[6], task->thread.acrs[7]);
  227. buffer += sprintf(buffer, " %08x %08x %08x %08x\n",
  228. task->thread.acrs[8], task->thread.acrs[9],
  229. task->thread.acrs[10], task->thread.acrs[11]);
  230. buffer += sprintf(buffer, " %08x %08x %08x %08x\n",
  231. task->thread.acrs[12], task->thread.acrs[13],
  232. task->thread.acrs[14], task->thread.acrs[15]);
  233. return buffer;
  234. }
  235. static DEFINE_SPINLOCK(die_lock);
  236. void die(const char * str, struct pt_regs * regs, long err)
  237. {
  238. static int die_counter;
  239. oops_enter();
  240. debug_stop_all();
  241. console_verbose();
  242. spin_lock_irq(&die_lock);
  243. bust_spinlocks(1);
  244. printk("%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
  245. #ifdef CONFIG_PREEMPT
  246. printk("PREEMPT ");
  247. #endif
  248. #ifdef CONFIG_SMP
  249. printk("SMP");
  250. #endif
  251. printk("\n");
  252. notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
  253. show_regs(regs);
  254. bust_spinlocks(0);
  255. add_taint(TAINT_DIE);
  256. spin_unlock_irq(&die_lock);
  257. if (in_interrupt())
  258. panic("Fatal exception in interrupt");
  259. if (panic_on_oops)
  260. panic("Fatal exception: panic_on_oops");
  261. oops_exit();
  262. do_exit(SIGSEGV);
  263. }
  264. static void inline
  265. report_user_fault(long interruption_code, struct pt_regs *regs)
  266. {
  267. #if defined(CONFIG_SYSCTL)
  268. if (!sysctl_userprocess_debug)
  269. return;
  270. #endif
  271. #if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG)
  272. printk("User process fault: interruption code 0x%lX\n",
  273. interruption_code);
  274. show_regs(regs);
  275. #endif
  276. }
  277. int is_valid_bugaddr(unsigned long addr)
  278. {
  279. return 1;
  280. }
  281. static void __kprobes inline do_trap(long interruption_code, int signr,
  282. char *str, struct pt_regs *regs,
  283. siginfo_t *info)
  284. {
  285. /*
  286. * We got all needed information from the lowcore and can
  287. * now safely switch on interrupts.
  288. */
  289. if (regs->psw.mask & PSW_MASK_PSTATE)
  290. local_irq_enable();
  291. if (notify_die(DIE_TRAP, str, regs, interruption_code,
  292. interruption_code, signr) == NOTIFY_STOP)
  293. return;
  294. if (regs->psw.mask & PSW_MASK_PSTATE) {
  295. struct task_struct *tsk = current;
  296. tsk->thread.trap_no = interruption_code & 0xffff;
  297. force_sig_info(signr, info, tsk);
  298. report_user_fault(interruption_code, regs);
  299. } else {
  300. const struct exception_table_entry *fixup;
  301. fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
  302. if (fixup)
  303. regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE;
  304. else {
  305. enum bug_trap_type btt;
  306. btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs);
  307. if (btt == BUG_TRAP_TYPE_WARN)
  308. return;
  309. die(str, regs, interruption_code);
  310. }
  311. }
  312. }
  313. static inline void __user *get_check_address(struct pt_regs *regs)
  314. {
  315. return (void __user *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN);
  316. }
  317. void __kprobes do_single_step(struct pt_regs *regs)
  318. {
  319. if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0,
  320. SIGTRAP) == NOTIFY_STOP){
  321. return;
  322. }
  323. if ((current->ptrace & PT_PTRACED) != 0)
  324. force_sig(SIGTRAP, current);
  325. }
  326. static void default_trap_handler(struct pt_regs * regs, long interruption_code)
  327. {
  328. if (regs->psw.mask & PSW_MASK_PSTATE) {
  329. local_irq_enable();
  330. do_exit(SIGSEGV);
  331. report_user_fault(interruption_code, regs);
  332. } else
  333. die("Unknown program exception", regs, interruption_code);
  334. }
  335. #define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \
  336. static void name(struct pt_regs * regs, long interruption_code) \
  337. { \
  338. siginfo_t info; \
  339. info.si_signo = signr; \
  340. info.si_errno = 0; \
  341. info.si_code = sicode; \
  342. info.si_addr = siaddr; \
  343. do_trap(interruption_code, signr, str, regs, &info); \
  344. }
  345. DO_ERROR_INFO(SIGILL, "addressing exception", addressing_exception,
  346. ILL_ILLADR, get_check_address(regs))
  347. DO_ERROR_INFO(SIGILL, "execute exception", execute_exception,
  348. ILL_ILLOPN, get_check_address(regs))
  349. DO_ERROR_INFO(SIGFPE, "fixpoint divide exception", divide_exception,
  350. FPE_INTDIV, get_check_address(regs))
  351. DO_ERROR_INFO(SIGFPE, "fixpoint overflow exception", overflow_exception,
  352. FPE_INTOVF, get_check_address(regs))
  353. DO_ERROR_INFO(SIGFPE, "HFP overflow exception", hfp_overflow_exception,
  354. FPE_FLTOVF, get_check_address(regs))
  355. DO_ERROR_INFO(SIGFPE, "HFP underflow exception", hfp_underflow_exception,
  356. FPE_FLTUND, get_check_address(regs))
  357. DO_ERROR_INFO(SIGFPE, "HFP significance exception", hfp_significance_exception,
  358. FPE_FLTRES, get_check_address(regs))
  359. DO_ERROR_INFO(SIGFPE, "HFP divide exception", hfp_divide_exception,
  360. FPE_FLTDIV, get_check_address(regs))
  361. DO_ERROR_INFO(SIGFPE, "HFP square root exception", hfp_sqrt_exception,
  362. FPE_FLTINV, get_check_address(regs))
  363. DO_ERROR_INFO(SIGILL, "operand exception", operand_exception,
  364. ILL_ILLOPN, get_check_address(regs))
  365. DO_ERROR_INFO(SIGILL, "privileged operation", privileged_op,
  366. ILL_PRVOPC, get_check_address(regs))
  367. DO_ERROR_INFO(SIGILL, "special operation exception", special_op_exception,
  368. ILL_ILLOPN, get_check_address(regs))
  369. DO_ERROR_INFO(SIGILL, "translation exception", translation_exception,
  370. ILL_ILLOPN, get_check_address(regs))
  371. static inline void
  372. do_fp_trap(struct pt_regs *regs, void __user *location,
  373. int fpc, long interruption_code)
  374. {
  375. siginfo_t si;
  376. si.si_signo = SIGFPE;
  377. si.si_errno = 0;
  378. si.si_addr = location;
  379. si.si_code = 0;
  380. /* FPC[2] is Data Exception Code */
  381. if ((fpc & 0x00000300) == 0) {
  382. /* bits 6 and 7 of DXC are 0 iff IEEE exception */
  383. if (fpc & 0x8000) /* invalid fp operation */
  384. si.si_code = FPE_FLTINV;
  385. else if (fpc & 0x4000) /* div by 0 */
  386. si.si_code = FPE_FLTDIV;
  387. else if (fpc & 0x2000) /* overflow */
  388. si.si_code = FPE_FLTOVF;
  389. else if (fpc & 0x1000) /* underflow */
  390. si.si_code = FPE_FLTUND;
  391. else if (fpc & 0x0800) /* inexact */
  392. si.si_code = FPE_FLTRES;
  393. }
  394. current->thread.ieee_instruction_pointer = (addr_t) location;
  395. do_trap(interruption_code, SIGFPE,
  396. "floating point exception", regs, &si);
  397. }
  398. static void illegal_op(struct pt_regs * regs, long interruption_code)
  399. {
  400. siginfo_t info;
  401. __u8 opcode[6];
  402. __u16 __user *location;
  403. int signal = 0;
  404. location = get_check_address(regs);
  405. /*
  406. * We got all needed information from the lowcore and can
  407. * now safely switch on interrupts.
  408. */
  409. if (regs->psw.mask & PSW_MASK_PSTATE)
  410. local_irq_enable();
  411. if (regs->psw.mask & PSW_MASK_PSTATE) {
  412. if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
  413. return;
  414. if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
  415. if (current->ptrace & PT_PTRACED)
  416. force_sig(SIGTRAP, current);
  417. else
  418. signal = SIGILL;
  419. #ifdef CONFIG_MATHEMU
  420. } else if (opcode[0] == 0xb3) {
  421. if (get_user(*((__u16 *) (opcode+2)), location+1))
  422. return;
  423. signal = math_emu_b3(opcode, regs);
  424. } else if (opcode[0] == 0xed) {
  425. if (get_user(*((__u32 *) (opcode+2)),
  426. (__u32 __user *)(location+1)))
  427. return;
  428. signal = math_emu_ed(opcode, regs);
  429. } else if (*((__u16 *) opcode) == 0xb299) {
  430. if (get_user(*((__u16 *) (opcode+2)), location+1))
  431. return;
  432. signal = math_emu_srnm(opcode, regs);
  433. } else if (*((__u16 *) opcode) == 0xb29c) {
  434. if (get_user(*((__u16 *) (opcode+2)), location+1))
  435. return;
  436. signal = math_emu_stfpc(opcode, regs);
  437. } else if (*((__u16 *) opcode) == 0xb29d) {
  438. if (get_user(*((__u16 *) (opcode+2)), location+1))
  439. return;
  440. signal = math_emu_lfpc(opcode, regs);
  441. #endif
  442. } else
  443. signal = SIGILL;
  444. } else {
  445. /*
  446. * If we get an illegal op in kernel mode, send it through the
  447. * kprobes notifier. If kprobes doesn't pick it up, SIGILL
  448. */
  449. if (notify_die(DIE_BPT, "bpt", regs, interruption_code,
  450. 3, SIGTRAP) != NOTIFY_STOP)
  451. signal = SIGILL;
  452. }
  453. #ifdef CONFIG_MATHEMU
  454. if (signal == SIGFPE)
  455. do_fp_trap(regs, location,
  456. current->thread.fp_regs.fpc, interruption_code);
  457. else if (signal == SIGSEGV) {
  458. info.si_signo = signal;
  459. info.si_errno = 0;
  460. info.si_code = SEGV_MAPERR;
  461. info.si_addr = (void __user *) location;
  462. do_trap(interruption_code, signal,
  463. "user address fault", regs, &info);
  464. } else
  465. #endif
  466. if (signal) {
  467. info.si_signo = signal;
  468. info.si_errno = 0;
  469. info.si_code = ILL_ILLOPC;
  470. info.si_addr = (void __user *) location;
  471. do_trap(interruption_code, signal,
  472. "illegal operation", regs, &info);
  473. }
  474. }
  475. #ifdef CONFIG_MATHEMU
  476. asmlinkage void
  477. specification_exception(struct pt_regs * regs, long interruption_code)
  478. {
  479. __u8 opcode[6];
  480. __u16 __user *location = NULL;
  481. int signal = 0;
  482. location = (__u16 __user *) get_check_address(regs);
  483. /*
  484. * We got all needed information from the lowcore and can
  485. * now safely switch on interrupts.
  486. */
  487. if (regs->psw.mask & PSW_MASK_PSTATE)
  488. local_irq_enable();
  489. if (regs->psw.mask & PSW_MASK_PSTATE) {
  490. get_user(*((__u16 *) opcode), location);
  491. switch (opcode[0]) {
  492. case 0x28: /* LDR Rx,Ry */
  493. signal = math_emu_ldr(opcode);
  494. break;
  495. case 0x38: /* LER Rx,Ry */
  496. signal = math_emu_ler(opcode);
  497. break;
  498. case 0x60: /* STD R,D(X,B) */
  499. get_user(*((__u16 *) (opcode+2)), location+1);
  500. signal = math_emu_std(opcode, regs);
  501. break;
  502. case 0x68: /* LD R,D(X,B) */
  503. get_user(*((__u16 *) (opcode+2)), location+1);
  504. signal = math_emu_ld(opcode, regs);
  505. break;
  506. case 0x70: /* STE R,D(X,B) */
  507. get_user(*((__u16 *) (opcode+2)), location+1);
  508. signal = math_emu_ste(opcode, regs);
  509. break;
  510. case 0x78: /* LE R,D(X,B) */
  511. get_user(*((__u16 *) (opcode+2)), location+1);
  512. signal = math_emu_le(opcode, regs);
  513. break;
  514. default:
  515. signal = SIGILL;
  516. break;
  517. }
  518. } else
  519. signal = SIGILL;
  520. if (signal == SIGFPE)
  521. do_fp_trap(regs, location,
  522. current->thread.fp_regs.fpc, interruption_code);
  523. else if (signal) {
  524. siginfo_t info;
  525. info.si_signo = signal;
  526. info.si_errno = 0;
  527. info.si_code = ILL_ILLOPN;
  528. info.si_addr = location;
  529. do_trap(interruption_code, signal,
  530. "specification exception", regs, &info);
  531. }
  532. }
  533. #else
  534. DO_ERROR_INFO(SIGILL, "specification exception", specification_exception,
  535. ILL_ILLOPN, get_check_address(regs));
  536. #endif
  537. static void data_exception(struct pt_regs * regs, long interruption_code)
  538. {
  539. __u16 __user *location;
  540. int signal = 0;
  541. location = get_check_address(regs);
  542. /*
  543. * We got all needed information from the lowcore and can
  544. * now safely switch on interrupts.
  545. */
  546. if (regs->psw.mask & PSW_MASK_PSTATE)
  547. local_irq_enable();
  548. if (MACHINE_HAS_IEEE)
  549. asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
  550. #ifdef CONFIG_MATHEMU
  551. else if (regs->psw.mask & PSW_MASK_PSTATE) {
  552. __u8 opcode[6];
  553. get_user(*((__u16 *) opcode), location);
  554. switch (opcode[0]) {
  555. case 0x28: /* LDR Rx,Ry */
  556. signal = math_emu_ldr(opcode);
  557. break;
  558. case 0x38: /* LER Rx,Ry */
  559. signal = math_emu_ler(opcode);
  560. break;
  561. case 0x60: /* STD R,D(X,B) */
  562. get_user(*((__u16 *) (opcode+2)), location+1);
  563. signal = math_emu_std(opcode, regs);
  564. break;
  565. case 0x68: /* LD R,D(X,B) */
  566. get_user(*((__u16 *) (opcode+2)), location+1);
  567. signal = math_emu_ld(opcode, regs);
  568. break;
  569. case 0x70: /* STE R,D(X,B) */
  570. get_user(*((__u16 *) (opcode+2)), location+1);
  571. signal = math_emu_ste(opcode, regs);
  572. break;
  573. case 0x78: /* LE R,D(X,B) */
  574. get_user(*((__u16 *) (opcode+2)), location+1);
  575. signal = math_emu_le(opcode, regs);
  576. break;
  577. case 0xb3:
  578. get_user(*((__u16 *) (opcode+2)), location+1);
  579. signal = math_emu_b3(opcode, regs);
  580. break;
  581. case 0xed:
  582. get_user(*((__u32 *) (opcode+2)),
  583. (__u32 __user *)(location+1));
  584. signal = math_emu_ed(opcode, regs);
  585. break;
  586. case 0xb2:
  587. if (opcode[1] == 0x99) {
  588. get_user(*((__u16 *) (opcode+2)), location+1);
  589. signal = math_emu_srnm(opcode, regs);
  590. } else if (opcode[1] == 0x9c) {
  591. get_user(*((__u16 *) (opcode+2)), location+1);
  592. signal = math_emu_stfpc(opcode, regs);
  593. } else if (opcode[1] == 0x9d) {
  594. get_user(*((__u16 *) (opcode+2)), location+1);
  595. signal = math_emu_lfpc(opcode, regs);
  596. } else
  597. signal = SIGILL;
  598. break;
  599. default:
  600. signal = SIGILL;
  601. break;
  602. }
  603. }
  604. #endif
  605. if (current->thread.fp_regs.fpc & FPC_DXC_MASK)
  606. signal = SIGFPE;
  607. else
  608. signal = SIGILL;
  609. if (signal == SIGFPE)
  610. do_fp_trap(regs, location,
  611. current->thread.fp_regs.fpc, interruption_code);
  612. else if (signal) {
  613. siginfo_t info;
  614. info.si_signo = signal;
  615. info.si_errno = 0;
  616. info.si_code = ILL_ILLOPN;
  617. info.si_addr = location;
  618. do_trap(interruption_code, signal,
  619. "data exception", regs, &info);
  620. }
  621. }
  622. static void space_switch_exception(struct pt_regs * regs, long int_code)
  623. {
  624. siginfo_t info;
  625. /* Set user psw back to home space mode. */
  626. if (regs->psw.mask & PSW_MASK_PSTATE)
  627. regs->psw.mask |= PSW_ASC_HOME;
  628. /* Send SIGILL. */
  629. info.si_signo = SIGILL;
  630. info.si_errno = 0;
  631. info.si_code = ILL_PRVOPC;
  632. info.si_addr = get_check_address(regs);
  633. do_trap(int_code, SIGILL, "space switch event", regs, &info);
  634. }
  635. asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
  636. {
  637. bust_spinlocks(1);
  638. printk("Kernel stack overflow.\n");
  639. show_regs(regs);
  640. bust_spinlocks(0);
  641. panic("Corrupt kernel stack, can't continue.");
  642. }
  643. /* init is done in lowcore.S and head.S */
  644. void __init trap_init(void)
  645. {
  646. int i;
  647. for (i = 0; i < 128; i++)
  648. pgm_check_table[i] = &default_trap_handler;
  649. pgm_check_table[1] = &illegal_op;
  650. pgm_check_table[2] = &privileged_op;
  651. pgm_check_table[3] = &execute_exception;
  652. pgm_check_table[4] = &do_protection_exception;
  653. pgm_check_table[5] = &addressing_exception;
  654. pgm_check_table[6] = &specification_exception;
  655. pgm_check_table[7] = &data_exception;
  656. pgm_check_table[8] = &overflow_exception;
  657. pgm_check_table[9] = &divide_exception;
  658. pgm_check_table[0x0A] = &overflow_exception;
  659. pgm_check_table[0x0B] = &divide_exception;
  660. pgm_check_table[0x0C] = &hfp_overflow_exception;
  661. pgm_check_table[0x0D] = &hfp_underflow_exception;
  662. pgm_check_table[0x0E] = &hfp_significance_exception;
  663. pgm_check_table[0x0F] = &hfp_divide_exception;
  664. pgm_check_table[0x10] = &do_dat_exception;
  665. pgm_check_table[0x11] = &do_dat_exception;
  666. pgm_check_table[0x12] = &translation_exception;
  667. pgm_check_table[0x13] = &special_op_exception;
  668. #ifdef CONFIG_64BIT
  669. pgm_check_table[0x38] = &do_dat_exception;
  670. pgm_check_table[0x39] = &do_dat_exception;
  671. pgm_check_table[0x3A] = &do_dat_exception;
  672. pgm_check_table[0x3B] = &do_dat_exception;
  673. #endif /* CONFIG_64BIT */
  674. pgm_check_table[0x15] = &operand_exception;
  675. pgm_check_table[0x1C] = &space_switch_exception;
  676. pgm_check_table[0x1D] = &hfp_sqrt_exception;
  677. pgm_check_table[0x40] = &do_monitor_call;
  678. pfault_irq_init();
  679. }