traps.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * S390 version
  4. * Copyright IBM Corp. 1999, 2000
  5. * Author(s): Martin Schwidefsky ([email protected]),
  6. * Denis Joseph Barrow ([email protected],[email protected]),
  7. *
  8. * Derived from "arch/i386/kernel/traps.c"
  9. * Copyright (C) 1991, 1992 Linus Torvalds
  10. */
  11. /*
  12. * 'Traps.c' handles hardware traps and faults after we have saved some
  13. * state in 'asm.s'.
  14. */
  15. #include "asm/irqflags.h"
  16. #include "asm/ptrace.h"
  17. #include <linux/kprobes.h>
  18. #include <linux/kdebug.h>
  19. #include <linux/randomize_kstack.h>
  20. #include <linux/extable.h>
  21. #include <linux/ptrace.h>
  22. #include <linux/sched.h>
  23. #include <linux/sched/debug.h>
  24. #include <linux/mm.h>
  25. #include <linux/slab.h>
  26. #include <linux/uaccess.h>
  27. #include <linux/cpu.h>
  28. #include <linux/entry-common.h>
  29. #include <asm/asm-extable.h>
  30. #include <asm/fpu/api.h>
  31. #include <asm/vtime.h>
  32. #include "entry.h"
  33. static inline void __user *get_trap_ip(struct pt_regs *regs)
  34. {
  35. unsigned long address;
  36. if (regs->int_code & 0x200)
  37. address = current->thread.trap_tdb.data[3];
  38. else
  39. address = regs->psw.addr;
  40. return (void __user *) (address - (regs->int_code >> 16));
  41. }
  42. int is_valid_bugaddr(unsigned long addr)
  43. {
  44. return 1;
  45. }
  46. void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str)
  47. {
  48. if (user_mode(regs)) {
  49. force_sig_fault(si_signo, si_code, get_trap_ip(regs));
  50. report_user_fault(regs, si_signo, 0);
  51. } else {
  52. if (!fixup_exception(regs))
  53. die(regs, str);
  54. }
  55. }
  56. static void do_trap(struct pt_regs *regs, int si_signo, int si_code, char *str)
  57. {
  58. if (notify_die(DIE_TRAP, str, regs, 0,
  59. regs->int_code, si_signo) == NOTIFY_STOP)
  60. return;
  61. do_report_trap(regs, si_signo, si_code, str);
  62. }
  63. NOKPROBE_SYMBOL(do_trap);
  64. void do_per_trap(struct pt_regs *regs)
  65. {
  66. if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
  67. return;
  68. if (!current->ptrace)
  69. return;
  70. force_sig_fault(SIGTRAP, TRAP_HWBKPT,
  71. (void __force __user *) current->thread.per_event.address);
  72. }
  73. NOKPROBE_SYMBOL(do_per_trap);
  74. static void default_trap_handler(struct pt_regs *regs)
  75. {
  76. if (user_mode(regs)) {
  77. report_user_fault(regs, SIGSEGV, 0);
  78. force_exit_sig(SIGSEGV);
  79. } else
  80. die(regs, "Unknown program exception");
  81. }
  82. #define DO_ERROR_INFO(name, signr, sicode, str) \
  83. static void name(struct pt_regs *regs) \
  84. { \
  85. do_trap(regs, signr, sicode, str); \
  86. }
  87. DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR,
  88. "addressing exception")
  89. DO_ERROR_INFO(execute_exception, SIGILL, ILL_ILLOPN,
  90. "execute exception")
  91. DO_ERROR_INFO(divide_exception, SIGFPE, FPE_INTDIV,
  92. "fixpoint divide exception")
  93. DO_ERROR_INFO(overflow_exception, SIGFPE, FPE_INTOVF,
  94. "fixpoint overflow exception")
  95. DO_ERROR_INFO(hfp_overflow_exception, SIGFPE, FPE_FLTOVF,
  96. "HFP overflow exception")
  97. DO_ERROR_INFO(hfp_underflow_exception, SIGFPE, FPE_FLTUND,
  98. "HFP underflow exception")
  99. DO_ERROR_INFO(hfp_significance_exception, SIGFPE, FPE_FLTRES,
  100. "HFP significance exception")
  101. DO_ERROR_INFO(hfp_divide_exception, SIGFPE, FPE_FLTDIV,
  102. "HFP divide exception")
  103. DO_ERROR_INFO(hfp_sqrt_exception, SIGFPE, FPE_FLTINV,
  104. "HFP square root exception")
  105. DO_ERROR_INFO(operand_exception, SIGILL, ILL_ILLOPN,
  106. "operand exception")
  107. DO_ERROR_INFO(privileged_op, SIGILL, ILL_PRVOPC,
  108. "privileged operation")
  109. DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN,
  110. "special operation exception")
  111. DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN,
  112. "transaction constraint exception")
  113. static inline void do_fp_trap(struct pt_regs *regs, __u32 fpc)
  114. {
  115. int si_code = 0;
  116. /* FPC[2] is Data Exception Code */
  117. if ((fpc & 0x00000300) == 0) {
  118. /* bits 6 and 7 of DXC are 0 iff IEEE exception */
  119. if (fpc & 0x8000) /* invalid fp operation */
  120. si_code = FPE_FLTINV;
  121. else if (fpc & 0x4000) /* div by 0 */
  122. si_code = FPE_FLTDIV;
  123. else if (fpc & 0x2000) /* overflow */
  124. si_code = FPE_FLTOVF;
  125. else if (fpc & 0x1000) /* underflow */
  126. si_code = FPE_FLTUND;
  127. else if (fpc & 0x0800) /* inexact */
  128. si_code = FPE_FLTRES;
  129. }
  130. do_trap(regs, SIGFPE, si_code, "floating point exception");
  131. }
  132. static void translation_specification_exception(struct pt_regs *regs)
  133. {
  134. /* May never happen. */
  135. panic("Translation-Specification Exception");
  136. }
  137. static void illegal_op(struct pt_regs *regs)
  138. {
  139. __u8 opcode[6];
  140. __u16 __user *location;
  141. int is_uprobe_insn = 0;
  142. int signal = 0;
  143. location = get_trap_ip(regs);
  144. if (user_mode(regs)) {
  145. if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
  146. return;
  147. if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
  148. if (current->ptrace)
  149. force_sig_fault(SIGTRAP, TRAP_BRKPT, location);
  150. else
  151. signal = SIGILL;
  152. #ifdef CONFIG_UPROBES
  153. } else if (*((__u16 *) opcode) == UPROBE_SWBP_INSN) {
  154. is_uprobe_insn = 1;
  155. #endif
  156. } else
  157. signal = SIGILL;
  158. }
  159. /*
  160. * We got either an illegal op in kernel mode, or user space trapped
  161. * on a uprobes illegal instruction. See if kprobes or uprobes picks
  162. * it up. If not, SIGILL.
  163. */
  164. if (is_uprobe_insn || !user_mode(regs)) {
  165. if (notify_die(DIE_BPT, "bpt", regs, 0,
  166. 3, SIGTRAP) != NOTIFY_STOP)
  167. signal = SIGILL;
  168. }
  169. if (signal)
  170. do_trap(regs, signal, ILL_ILLOPC, "illegal operation");
  171. }
  172. NOKPROBE_SYMBOL(illegal_op);
  173. DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
  174. "specification exception");
  175. static void vector_exception(struct pt_regs *regs)
  176. {
  177. int si_code, vic;
  178. if (!MACHINE_HAS_VX) {
  179. do_trap(regs, SIGILL, ILL_ILLOPN, "illegal operation");
  180. return;
  181. }
  182. /* get vector interrupt code from fpc */
  183. save_fpu_regs();
  184. vic = (current->thread.fpu.fpc & 0xf00) >> 8;
  185. switch (vic) {
  186. case 1: /* invalid vector operation */
  187. si_code = FPE_FLTINV;
  188. break;
  189. case 2: /* division by zero */
  190. si_code = FPE_FLTDIV;
  191. break;
  192. case 3: /* overflow */
  193. si_code = FPE_FLTOVF;
  194. break;
  195. case 4: /* underflow */
  196. si_code = FPE_FLTUND;
  197. break;
  198. case 5: /* inexact */
  199. si_code = FPE_FLTRES;
  200. break;
  201. default: /* unknown cause */
  202. si_code = 0;
  203. }
  204. do_trap(regs, SIGFPE, si_code, "vector exception");
  205. }
  206. static void data_exception(struct pt_regs *regs)
  207. {
  208. save_fpu_regs();
  209. if (current->thread.fpu.fpc & FPC_DXC_MASK)
  210. do_fp_trap(regs, current->thread.fpu.fpc);
  211. else
  212. do_trap(regs, SIGILL, ILL_ILLOPN, "data exception");
  213. }
  214. static void space_switch_exception(struct pt_regs *regs)
  215. {
  216. /* Set user psw back to home space mode. */
  217. if (user_mode(regs))
  218. regs->psw.mask |= PSW_ASC_HOME;
  219. /* Send SIGILL. */
  220. do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event");
  221. }
  222. static void monitor_event_exception(struct pt_regs *regs)
  223. {
  224. if (user_mode(regs))
  225. return;
  226. switch (report_bug(regs->psw.addr - (regs->int_code >> 16), regs)) {
  227. case BUG_TRAP_TYPE_NONE:
  228. fixup_exception(regs);
  229. break;
  230. case BUG_TRAP_TYPE_WARN:
  231. break;
  232. case BUG_TRAP_TYPE_BUG:
  233. die(regs, "monitor event");
  234. break;
  235. }
  236. }
  237. void kernel_stack_overflow(struct pt_regs *regs)
  238. {
  239. bust_spinlocks(1);
  240. printk("Kernel stack overflow.\n");
  241. show_regs(regs);
  242. bust_spinlocks(0);
  243. panic("Corrupt kernel stack, can't continue.");
  244. }
  245. NOKPROBE_SYMBOL(kernel_stack_overflow);
  246. static void __init test_monitor_call(void)
  247. {
  248. int val = 1;
  249. if (!IS_ENABLED(CONFIG_BUG))
  250. return;
  251. asm volatile(
  252. " mc 0,0\n"
  253. "0: xgr %0,%0\n"
  254. "1:\n"
  255. EX_TABLE(0b,1b)
  256. : "+d" (val));
  257. if (!val)
  258. panic("Monitor call doesn't work!\n");
  259. }
  260. void __init trap_init(void)
  261. {
  262. local_mcck_enable();
  263. test_monitor_call();
  264. }
  265. static void (*pgm_check_table[128])(struct pt_regs *regs);
  266. void noinstr __do_pgm_check(struct pt_regs *regs)
  267. {
  268. unsigned int trapnr;
  269. irqentry_state_t state;
  270. regs->int_code = S390_lowcore.pgm_int_code;
  271. regs->int_parm_long = S390_lowcore.trans_exc_code;
  272. state = irqentry_enter(regs);
  273. if (user_mode(regs)) {
  274. update_timer_sys();
  275. if (!static_branch_likely(&cpu_has_bear)) {
  276. if (regs->last_break < 4096)
  277. regs->last_break = 1;
  278. }
  279. current->thread.last_break = regs->last_break;
  280. }
  281. if (S390_lowcore.pgm_code & 0x0200) {
  282. /* transaction abort */
  283. current->thread.trap_tdb = S390_lowcore.pgm_tdb;
  284. }
  285. if (S390_lowcore.pgm_code & PGM_INT_CODE_PER) {
  286. if (user_mode(regs)) {
  287. struct per_event *ev = &current->thread.per_event;
  288. set_thread_flag(TIF_PER_TRAP);
  289. ev->address = S390_lowcore.per_address;
  290. ev->cause = S390_lowcore.per_code_combined;
  291. ev->paid = S390_lowcore.per_access_id;
  292. } else {
  293. /* PER event in kernel is kprobes */
  294. __arch_local_irq_ssm(regs->psw.mask & ~PSW_MASK_PER);
  295. do_per_trap(regs);
  296. goto out;
  297. }
  298. }
  299. if (!irqs_disabled_flags(regs->psw.mask))
  300. trace_hardirqs_on();
  301. __arch_local_irq_ssm(regs->psw.mask & ~PSW_MASK_PER);
  302. trapnr = regs->int_code & PGM_INT_CODE_MASK;
  303. if (trapnr)
  304. pgm_check_table[trapnr](regs);
  305. out:
  306. local_irq_disable();
  307. irqentry_exit(regs, state);
  308. }
  309. /*
  310. * The program check table contains exactly 128 (0x00-0x7f) entries. Each
  311. * line defines the function to be called corresponding to the program check
  312. * interruption code.
  313. */
  314. static void (*pgm_check_table[128])(struct pt_regs *regs) = {
  315. [0x00] = default_trap_handler,
  316. [0x01] = illegal_op,
  317. [0x02] = privileged_op,
  318. [0x03] = execute_exception,
  319. [0x04] = do_protection_exception,
  320. [0x05] = addressing_exception,
  321. [0x06] = specification_exception,
  322. [0x07] = data_exception,
  323. [0x08] = overflow_exception,
  324. [0x09] = divide_exception,
  325. [0x0a] = overflow_exception,
  326. [0x0b] = divide_exception,
  327. [0x0c] = hfp_overflow_exception,
  328. [0x0d] = hfp_underflow_exception,
  329. [0x0e] = hfp_significance_exception,
  330. [0x0f] = hfp_divide_exception,
  331. [0x10] = do_dat_exception,
  332. [0x11] = do_dat_exception,
  333. [0x12] = translation_specification_exception,
  334. [0x13] = special_op_exception,
  335. [0x14] = default_trap_handler,
  336. [0x15] = operand_exception,
  337. [0x16] = default_trap_handler,
  338. [0x17] = default_trap_handler,
  339. [0x18] = transaction_exception,
  340. [0x19] = default_trap_handler,
  341. [0x1a] = default_trap_handler,
  342. [0x1b] = vector_exception,
  343. [0x1c] = space_switch_exception,
  344. [0x1d] = hfp_sqrt_exception,
  345. [0x1e ... 0x37] = default_trap_handler,
  346. [0x38] = do_dat_exception,
  347. [0x39] = do_dat_exception,
  348. [0x3a] = do_dat_exception,
  349. [0x3b] = do_dat_exception,
  350. [0x3c] = default_trap_handler,
  351. [0x3d] = do_secure_storage_access,
  352. [0x3e] = do_non_secure_storage_access,
  353. [0x3f] = do_secure_storage_violation,
  354. [0x40] = monitor_event_exception,
  355. [0x41 ... 0x7f] = default_trap_handler,
  356. };
  357. #define COND_TRAP(x) asm( \
  358. ".weak " __stringify(x) "\n\t" \
  359. ".set " __stringify(x) "," \
  360. __stringify(default_trap_handler))
  361. COND_TRAP(do_secure_storage_access);
  362. COND_TRAP(do_non_secure_storage_access);
  363. COND_TRAP(do_secure_storage_violation);