mce_power.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /*
  2. * Machine check exception handling CPU-side for power7 and power8
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. *
  18. * Copyright 2013 IBM Corporation
  19. * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
  20. */
  21. #undef DEBUG
  22. #define pr_fmt(fmt) "mce_power: " fmt
  23. #include <linux/types.h>
  24. #include <linux/ptrace.h>
  25. #include <asm/mmu.h>
  26. #include <asm/mce.h>
  27. #include <asm/machdep.h>
  28. #include <asm/pgtable.h>
  29. #include <asm/pte-walk.h>
  30. #include <asm/sstep.h>
  31. #include <asm/exception-64s.h>
  32. /*
  33. * Convert an address related to an mm to a PFN. NOTE: we are in real
  34. * mode, we could potentially race with page table updates.
  35. */
  36. static unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr)
  37. {
  38. pte_t *ptep;
  39. unsigned long flags;
  40. struct mm_struct *mm;
  41. if (user_mode(regs))
  42. mm = current->mm;
  43. else
  44. mm = &init_mm;
  45. local_irq_save(flags);
  46. if (mm == current->mm)
  47. ptep = find_current_mm_pte(mm->pgd, addr, NULL, NULL);
  48. else
  49. ptep = find_init_mm_pte(addr, NULL);
  50. local_irq_restore(flags);
  51. if (!ptep || pte_special(*ptep))
  52. return ULONG_MAX;
  53. return pte_pfn(*ptep);
  54. }
  55. /* flush SLBs and reload */
  56. #ifdef CONFIG_PPC_BOOK3S_64
  57. static void flush_and_reload_slb(void)
  58. {
  59. struct slb_shadow *slb;
  60. unsigned long i, n;
  61. /* Invalidate all SLBs */
  62. asm volatile("slbmte %0,%0; slbia" : : "r" (0));
  63. #ifdef CONFIG_KVM_BOOK3S_HANDLER
  64. /*
  65. * If machine check is hit when in guest or in transition, we will
  66. * only flush the SLBs and continue.
  67. */
  68. if (get_paca()->kvm_hstate.in_guest)
  69. return;
  70. #endif
  71. /* For host kernel, reload the SLBs from shadow SLB buffer. */
  72. slb = get_slb_shadow();
  73. if (!slb)
  74. return;
  75. n = min_t(u32, be32_to_cpu(slb->persistent), SLB_MIN_SIZE);
  76. /* Load up the SLB entries from shadow SLB */
  77. for (i = 0; i < n; i++) {
  78. unsigned long rb = be64_to_cpu(slb->save_area[i].esid);
  79. unsigned long rs = be64_to_cpu(slb->save_area[i].vsid);
  80. rb = (rb & ~0xFFFul) | i;
  81. asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
  82. }
  83. }
  84. #endif
  85. static void flush_erat(void)
  86. {
  87. asm volatile(PPC_INVALIDATE_ERAT : : :"memory");
  88. }
  89. #define MCE_FLUSH_SLB 1
  90. #define MCE_FLUSH_TLB 2
  91. #define MCE_FLUSH_ERAT 3
  92. static int mce_flush(int what)
  93. {
  94. #ifdef CONFIG_PPC_BOOK3S_64
  95. if (what == MCE_FLUSH_SLB) {
  96. flush_and_reload_slb();
  97. return 1;
  98. }
  99. #endif
  100. if (what == MCE_FLUSH_ERAT) {
  101. flush_erat();
  102. return 1;
  103. }
  104. if (what == MCE_FLUSH_TLB) {
  105. tlbiel_all();
  106. return 1;
  107. }
  108. return 0;
  109. }
  110. #define SRR1_MC_LOADSTORE(srr1) ((srr1) & PPC_BIT(42))
  111. struct mce_ierror_table {
  112. unsigned long srr1_mask;
  113. unsigned long srr1_value;
  114. bool nip_valid; /* nip is a valid indicator of faulting address */
  115. unsigned int error_type;
  116. unsigned int error_subtype;
  117. unsigned int initiator;
  118. unsigned int severity;
  119. };
  120. static const struct mce_ierror_table mce_p7_ierror_table[] = {
  121. { 0x00000000001c0000, 0x0000000000040000, true,
  122. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH,
  123. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  124. { 0x00000000001c0000, 0x0000000000080000, true,
  125. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY,
  126. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  127. { 0x00000000001c0000, 0x00000000000c0000, true,
  128. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT,
  129. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  130. { 0x00000000001c0000, 0x0000000000100000, true,
  131. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_INDETERMINATE, /* BOTH */
  132. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  133. { 0x00000000001c0000, 0x0000000000140000, true,
  134. MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT,
  135. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  136. { 0x00000000001c0000, 0x0000000000180000, true,
  137. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH,
  138. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  139. { 0x00000000001c0000, 0x00000000001c0000, true,
  140. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH,
  141. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  142. { 0, 0, 0, 0, 0, 0 } };
  143. static const struct mce_ierror_table mce_p8_ierror_table[] = {
  144. { 0x00000000081c0000, 0x0000000000040000, true,
  145. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH,
  146. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  147. { 0x00000000081c0000, 0x0000000000080000, true,
  148. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY,
  149. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  150. { 0x00000000081c0000, 0x00000000000c0000, true,
  151. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT,
  152. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  153. { 0x00000000081c0000, 0x0000000000100000, true,
  154. MCE_ERROR_TYPE_ERAT,MCE_ERAT_ERROR_MULTIHIT,
  155. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  156. { 0x00000000081c0000, 0x0000000000140000, true,
  157. MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT,
  158. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  159. { 0x00000000081c0000, 0x0000000000180000, true,
  160. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH,
  161. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  162. { 0x00000000081c0000, 0x00000000001c0000, true,
  163. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH,
  164. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  165. { 0x00000000081c0000, 0x0000000008000000, true,
  166. MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_IFETCH_TIMEOUT,
  167. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  168. { 0x00000000081c0000, 0x0000000008040000, true,
  169. MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT,
  170. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  171. { 0, 0, 0, 0, 0, 0 } };
  172. static const struct mce_ierror_table mce_p9_ierror_table[] = {
  173. { 0x00000000081c0000, 0x0000000000040000, true,
  174. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_IFETCH,
  175. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  176. { 0x00000000081c0000, 0x0000000000080000, true,
  177. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY,
  178. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  179. { 0x00000000081c0000, 0x00000000000c0000, true,
  180. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT,
  181. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  182. { 0x00000000081c0000, 0x0000000000100000, true,
  183. MCE_ERROR_TYPE_ERAT,MCE_ERAT_ERROR_MULTIHIT,
  184. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  185. { 0x00000000081c0000, 0x0000000000140000, true,
  186. MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT,
  187. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  188. { 0x00000000081c0000, 0x0000000000180000, true,
  189. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH,
  190. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  191. { 0x00000000081c0000, 0x00000000001c0000, true,
  192. MCE_ERROR_TYPE_RA, MCE_RA_ERROR_IFETCH_FOREIGN,
  193. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  194. { 0x00000000081c0000, 0x0000000008000000, true,
  195. MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_IFETCH_TIMEOUT,
  196. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  197. { 0x00000000081c0000, 0x0000000008040000, true,
  198. MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT,
  199. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  200. { 0x00000000081c0000, 0x00000000080c0000, true,
  201. MCE_ERROR_TYPE_RA, MCE_RA_ERROR_IFETCH,
  202. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  203. { 0x00000000081c0000, 0x0000000008100000, true,
  204. MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH,
  205. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  206. { 0x00000000081c0000, 0x0000000008140000, false,
  207. MCE_ERROR_TYPE_RA, MCE_RA_ERROR_STORE,
  208. MCE_INITIATOR_CPU, MCE_SEV_FATAL, }, /* ASYNC is fatal */
  209. { 0x00000000081c0000, 0x0000000008180000, false,
  210. MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_STORE_TIMEOUT,
  211. MCE_INITIATOR_CPU, MCE_SEV_FATAL, }, /* ASYNC is fatal */
  212. { 0x00000000081c0000, 0x00000000081c0000, true,
  213. MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN,
  214. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  215. { 0, 0, 0, 0, 0, 0 } };
  216. struct mce_derror_table {
  217. unsigned long dsisr_value;
  218. bool dar_valid; /* dar is a valid indicator of faulting address */
  219. unsigned int error_type;
  220. unsigned int error_subtype;
  221. unsigned int initiator;
  222. unsigned int severity;
  223. };
  224. static const struct mce_derror_table mce_p7_derror_table[] = {
  225. { 0x00008000, false,
  226. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_LOAD_STORE,
  227. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  228. { 0x00004000, true,
  229. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE,
  230. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  231. { 0x00000800, true,
  232. MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT,
  233. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  234. { 0x00000400, true,
  235. MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT,
  236. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  237. { 0x00000100, true,
  238. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY,
  239. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  240. { 0x00000080, true,
  241. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT,
  242. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  243. { 0x00000040, true,
  244. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_INDETERMINATE, /* BOTH */
  245. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  246. { 0, false, 0, 0, 0, 0 } };
  247. static const struct mce_derror_table mce_p8_derror_table[] = {
  248. { 0x00008000, false,
  249. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_LOAD_STORE,
  250. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  251. { 0x00004000, true,
  252. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE,
  253. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  254. { 0x00002000, true,
  255. MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_LOAD_TIMEOUT,
  256. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  257. { 0x00001000, true,
  258. MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT,
  259. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  260. { 0x00000800, true,
  261. MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT,
  262. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  263. { 0x00000400, true,
  264. MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT,
  265. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  266. { 0x00000200, true,
  267. MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT, /* SECONDARY ERAT */
  268. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  269. { 0x00000100, true,
  270. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY,
  271. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  272. { 0x00000080, true,
  273. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT,
  274. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  275. { 0, false, 0, 0, 0, 0 } };
  276. static const struct mce_derror_table mce_p9_derror_table[] = {
  277. { 0x00008000, false,
  278. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_LOAD_STORE,
  279. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  280. { 0x00004000, true,
  281. MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE,
  282. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  283. { 0x00002000, true,
  284. MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_LOAD_TIMEOUT,
  285. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  286. { 0x00001000, true,
  287. MCE_ERROR_TYPE_LINK, MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT,
  288. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  289. { 0x00000800, true,
  290. MCE_ERROR_TYPE_ERAT, MCE_ERAT_ERROR_MULTIHIT,
  291. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  292. { 0x00000400, true,
  293. MCE_ERROR_TYPE_TLB, MCE_TLB_ERROR_MULTIHIT,
  294. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  295. { 0x00000200, false,
  296. MCE_ERROR_TYPE_USER, MCE_USER_ERROR_TLBIE,
  297. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  298. { 0x00000100, true,
  299. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_PARITY,
  300. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  301. { 0x00000080, true,
  302. MCE_ERROR_TYPE_SLB, MCE_SLB_ERROR_MULTIHIT,
  303. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  304. { 0x00000040, true,
  305. MCE_ERROR_TYPE_RA, MCE_RA_ERROR_LOAD,
  306. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  307. { 0x00000020, false,
  308. MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE,
  309. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  310. { 0x00000010, false,
  311. MCE_ERROR_TYPE_RA, MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN,
  312. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  313. { 0x00000008, false,
  314. MCE_ERROR_TYPE_RA, MCE_RA_ERROR_LOAD_STORE_FOREIGN,
  315. MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
  316. { 0, false, 0, 0, 0, 0 } };
  317. static int mce_find_instr_ea_and_pfn(struct pt_regs *regs, uint64_t *addr,
  318. uint64_t *phys_addr)
  319. {
  320. /*
  321. * Carefully look at the NIP to determine
  322. * the instruction to analyse. Reading the NIP
  323. * in real-mode is tricky and can lead to recursive
  324. * faults
  325. */
  326. int instr;
  327. unsigned long pfn, instr_addr;
  328. struct instruction_op op;
  329. struct pt_regs tmp = *regs;
  330. pfn = addr_to_pfn(regs, regs->nip);
  331. if (pfn != ULONG_MAX) {
  332. instr_addr = (pfn << PAGE_SHIFT) + (regs->nip & ~PAGE_MASK);
  333. instr = *(unsigned int *)(instr_addr);
  334. if (!analyse_instr(&op, &tmp, instr)) {
  335. pfn = addr_to_pfn(regs, op.ea);
  336. *addr = op.ea;
  337. *phys_addr = (pfn << PAGE_SHIFT);
  338. return 0;
  339. }
  340. /*
  341. * analyse_instr() might fail if the instruction
  342. * is not a load/store, although this is unexpected
  343. * for load/store errors or if we got the NIP
  344. * wrong
  345. */
  346. }
  347. *addr = 0;
  348. return -1;
  349. }
  350. static int mce_handle_ierror(struct pt_regs *regs,
  351. const struct mce_ierror_table table[],
  352. struct mce_error_info *mce_err, uint64_t *addr,
  353. uint64_t *phys_addr)
  354. {
  355. uint64_t srr1 = regs->msr;
  356. int handled = 0;
  357. int i;
  358. *addr = 0;
  359. for (i = 0; table[i].srr1_mask; i++) {
  360. if ((srr1 & table[i].srr1_mask) != table[i].srr1_value)
  361. continue;
  362. /* attempt to correct the error */
  363. switch (table[i].error_type) {
  364. case MCE_ERROR_TYPE_SLB:
  365. handled = mce_flush(MCE_FLUSH_SLB);
  366. break;
  367. case MCE_ERROR_TYPE_ERAT:
  368. handled = mce_flush(MCE_FLUSH_ERAT);
  369. break;
  370. case MCE_ERROR_TYPE_TLB:
  371. handled = mce_flush(MCE_FLUSH_TLB);
  372. break;
  373. }
  374. /* now fill in mce_error_info */
  375. mce_err->error_type = table[i].error_type;
  376. switch (table[i].error_type) {
  377. case MCE_ERROR_TYPE_UE:
  378. mce_err->u.ue_error_type = table[i].error_subtype;
  379. break;
  380. case MCE_ERROR_TYPE_SLB:
  381. mce_err->u.slb_error_type = table[i].error_subtype;
  382. break;
  383. case MCE_ERROR_TYPE_ERAT:
  384. mce_err->u.erat_error_type = table[i].error_subtype;
  385. break;
  386. case MCE_ERROR_TYPE_TLB:
  387. mce_err->u.tlb_error_type = table[i].error_subtype;
  388. break;
  389. case MCE_ERROR_TYPE_USER:
  390. mce_err->u.user_error_type = table[i].error_subtype;
  391. break;
  392. case MCE_ERROR_TYPE_RA:
  393. mce_err->u.ra_error_type = table[i].error_subtype;
  394. break;
  395. case MCE_ERROR_TYPE_LINK:
  396. mce_err->u.link_error_type = table[i].error_subtype;
  397. break;
  398. }
  399. mce_err->severity = table[i].severity;
  400. mce_err->initiator = table[i].initiator;
  401. if (table[i].nip_valid) {
  402. *addr = regs->nip;
  403. if (mce_err->severity == MCE_SEV_ERROR_SYNC &&
  404. table[i].error_type == MCE_ERROR_TYPE_UE) {
  405. unsigned long pfn;
  406. if (get_paca()->in_mce < MAX_MCE_DEPTH) {
  407. pfn = addr_to_pfn(regs, regs->nip);
  408. if (pfn != ULONG_MAX) {
  409. *phys_addr =
  410. (pfn << PAGE_SHIFT);
  411. }
  412. }
  413. }
  414. }
  415. return handled;
  416. }
  417. mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN;
  418. mce_err->severity = MCE_SEV_ERROR_SYNC;
  419. mce_err->initiator = MCE_INITIATOR_CPU;
  420. return 0;
  421. }
  422. static int mce_handle_derror(struct pt_regs *regs,
  423. const struct mce_derror_table table[],
  424. struct mce_error_info *mce_err, uint64_t *addr,
  425. uint64_t *phys_addr)
  426. {
  427. uint64_t dsisr = regs->dsisr;
  428. int handled = 0;
  429. int found = 0;
  430. int i;
  431. *addr = 0;
  432. for (i = 0; table[i].dsisr_value; i++) {
  433. if (!(dsisr & table[i].dsisr_value))
  434. continue;
  435. /* attempt to correct the error */
  436. switch (table[i].error_type) {
  437. case MCE_ERROR_TYPE_SLB:
  438. if (mce_flush(MCE_FLUSH_SLB))
  439. handled = 1;
  440. break;
  441. case MCE_ERROR_TYPE_ERAT:
  442. if (mce_flush(MCE_FLUSH_ERAT))
  443. handled = 1;
  444. break;
  445. case MCE_ERROR_TYPE_TLB:
  446. if (mce_flush(MCE_FLUSH_TLB))
  447. handled = 1;
  448. break;
  449. }
  450. /*
  451. * Attempt to handle multiple conditions, but only return
  452. * one. Ensure uncorrectable errors are first in the table
  453. * to match.
  454. */
  455. if (found)
  456. continue;
  457. /* now fill in mce_error_info */
  458. mce_err->error_type = table[i].error_type;
  459. switch (table[i].error_type) {
  460. case MCE_ERROR_TYPE_UE:
  461. mce_err->u.ue_error_type = table[i].error_subtype;
  462. break;
  463. case MCE_ERROR_TYPE_SLB:
  464. mce_err->u.slb_error_type = table[i].error_subtype;
  465. break;
  466. case MCE_ERROR_TYPE_ERAT:
  467. mce_err->u.erat_error_type = table[i].error_subtype;
  468. break;
  469. case MCE_ERROR_TYPE_TLB:
  470. mce_err->u.tlb_error_type = table[i].error_subtype;
  471. break;
  472. case MCE_ERROR_TYPE_USER:
  473. mce_err->u.user_error_type = table[i].error_subtype;
  474. break;
  475. case MCE_ERROR_TYPE_RA:
  476. mce_err->u.ra_error_type = table[i].error_subtype;
  477. break;
  478. case MCE_ERROR_TYPE_LINK:
  479. mce_err->u.link_error_type = table[i].error_subtype;
  480. break;
  481. }
  482. mce_err->severity = table[i].severity;
  483. mce_err->initiator = table[i].initiator;
  484. if (table[i].dar_valid)
  485. *addr = regs->dar;
  486. else if (mce_err->severity == MCE_SEV_ERROR_SYNC &&
  487. table[i].error_type == MCE_ERROR_TYPE_UE) {
  488. /*
  489. * We do a maximum of 4 nested MCE calls, see
  490. * kernel/exception-64s.h
  491. */
  492. if (get_paca()->in_mce < MAX_MCE_DEPTH)
  493. mce_find_instr_ea_and_pfn(regs, addr, phys_addr);
  494. }
  495. found = 1;
  496. }
  497. if (found)
  498. return handled;
  499. mce_err->error_type = MCE_ERROR_TYPE_UNKNOWN;
  500. mce_err->severity = MCE_SEV_ERROR_SYNC;
  501. mce_err->initiator = MCE_INITIATOR_CPU;
  502. return 0;
  503. }
  504. static long mce_handle_ue_error(struct pt_regs *regs)
  505. {
  506. long handled = 0;
  507. /*
  508. * On specific SCOM read via MMIO we may get a machine check
  509. * exception with SRR0 pointing inside opal. If that is the
  510. * case OPAL may have recovery address to re-read SCOM data in
  511. * different way and hence we can recover from this MC.
  512. */
  513. if (ppc_md.mce_check_early_recovery) {
  514. if (ppc_md.mce_check_early_recovery(regs))
  515. handled = 1;
  516. }
  517. return handled;
  518. }
  519. static long mce_handle_error(struct pt_regs *regs,
  520. const struct mce_derror_table dtable[],
  521. const struct mce_ierror_table itable[])
  522. {
  523. struct mce_error_info mce_err = { 0 };
  524. uint64_t addr, phys_addr = ULONG_MAX;
  525. uint64_t srr1 = regs->msr;
  526. long handled;
  527. if (SRR1_MC_LOADSTORE(srr1))
  528. handled = mce_handle_derror(regs, dtable, &mce_err, &addr,
  529. &phys_addr);
  530. else
  531. handled = mce_handle_ierror(regs, itable, &mce_err, &addr,
  532. &phys_addr);
  533. if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE)
  534. handled = mce_handle_ue_error(regs);
  535. save_mce_event(regs, handled, &mce_err, regs->nip, addr, phys_addr);
  536. return handled;
  537. }
  538. long __machine_check_early_realmode_p7(struct pt_regs *regs)
  539. {
  540. /* P7 DD1 leaves top bits of DSISR undefined */
  541. regs->dsisr &= 0x0000ffff;
  542. return mce_handle_error(regs, mce_p7_derror_table, mce_p7_ierror_table);
  543. }
  544. long __machine_check_early_realmode_p8(struct pt_regs *regs)
  545. {
  546. return mce_handle_error(regs, mce_p8_derror_table, mce_p8_ierror_table);
  547. }
  548. long __machine_check_early_realmode_p9(struct pt_regs *regs)
  549. {
  550. /*
  551. * On POWER9 DD2.1 and below, it's possible to get a machine check
  552. * caused by a paste instruction where only DSISR bit 25 is set. This
  553. * will result in the MCE handler seeing an unknown event and the kernel
  554. * crashing. An MCE that occurs like this is spurious, so we don't need
  555. * to do anything in terms of servicing it. If there is something that
  556. * needs to be serviced, the CPU will raise the MCE again with the
  557. * correct DSISR so that it can be serviced properly. So detect this
  558. * case and mark it as handled.
  559. */
  560. if (SRR1_MC_LOADSTORE(regs->msr) && regs->dsisr == 0x02000000)
  561. return 1;
  562. return mce_handle_error(regs, mce_p9_derror_table, mce_p9_ierror_table);
  563. }