traps.c 22 KB

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