ras.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Copyright (C) 2001 Dave Engebretsen IBM Corporation
  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. /* Change Activity:
  19. * 2001/09/21 : engebret : Created with minimal EPOW and HW exception support.
  20. * End Change Activity
  21. */
  22. #include <linux/errno.h>
  23. #include <linux/threads.h>
  24. #include <linux/kernel_stat.h>
  25. #include <linux/signal.h>
  26. #include <linux/sched.h>
  27. #include <linux/ioport.h>
  28. #include <linux/interrupt.h>
  29. #include <linux/timex.h>
  30. #include <linux/init.h>
  31. #include <linux/delay.h>
  32. #include <linux/irq.h>
  33. #include <linux/random.h>
  34. #include <linux/sysrq.h>
  35. #include <linux/bitops.h>
  36. #include <asm/uaccess.h>
  37. #include <asm/system.h>
  38. #include <asm/io.h>
  39. #include <asm/pgtable.h>
  40. #include <asm/irq.h>
  41. #include <asm/cache.h>
  42. #include <asm/prom.h>
  43. #include <asm/ptrace.h>
  44. #include <asm/machdep.h>
  45. #include <asm/rtas.h>
  46. #include <asm/udbg.h>
  47. #include <asm/firmware.h>
  48. #include "pseries.h"
  49. static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
  50. static DEFINE_SPINLOCK(ras_log_buf_lock);
  51. static char mce_data_buf[RTAS_ERROR_LOG_MAX];
  52. static int ras_get_sensor_state_token;
  53. static int ras_check_exception_token;
  54. #define EPOW_SENSOR_TOKEN 9
  55. #define EPOW_SENSOR_INDEX 0
  56. static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);
  57. static irqreturn_t ras_error_interrupt(int irq, void *dev_id);
  58. /*
  59. * Initialize handlers for the set of interrupts caused by hardware errors
  60. * and power system events.
  61. */
  62. static int __init init_ras_IRQ(void)
  63. {
  64. struct device_node *np;
  65. ras_get_sensor_state_token = rtas_token("get-sensor-state");
  66. ras_check_exception_token = rtas_token("check-exception");
  67. /* Internal Errors */
  68. np = of_find_node_by_path("/event-sources/internal-errors");
  69. if (np != NULL) {
  70. request_event_sources_irqs(np, ras_error_interrupt,
  71. "RAS_ERROR");
  72. of_node_put(np);
  73. }
  74. /* EPOW Events */
  75. np = of_find_node_by_path("/event-sources/epow-events");
  76. if (np != NULL) {
  77. request_event_sources_irqs(np, ras_epow_interrupt, "RAS_EPOW");
  78. of_node_put(np);
  79. }
  80. return 0;
  81. }
  82. __initcall(init_ras_IRQ);
  83. /*
  84. * Handle power subsystem events (EPOW).
  85. *
  86. * Presently we just log the event has occurred. This should be fixed
  87. * to examine the type of power failure and take appropriate action where
  88. * the time horizon permits something useful to be done.
  89. */
  90. static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
  91. {
  92. int status = 0xdeadbeef;
  93. int state = 0;
  94. int critical;
  95. status = rtas_call(ras_get_sensor_state_token, 2, 2, &state,
  96. EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX);
  97. if (state > 3)
  98. critical = 1; /* Time Critical */
  99. else
  100. critical = 0;
  101. spin_lock(&ras_log_buf_lock);
  102. status = rtas_call(ras_check_exception_token, 6, 1, NULL,
  103. RTAS_VECTOR_EXTERNAL_INTERRUPT,
  104. irq_map[irq].hwirq,
  105. RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
  106. critical, __pa(&ras_log_buf),
  107. rtas_get_error_log_max());
  108. udbg_printf("EPOW <0x%lx 0x%x 0x%x>\n",
  109. *((unsigned long *)&ras_log_buf), status, state);
  110. printk(KERN_WARNING "EPOW <0x%lx 0x%x 0x%x>\n",
  111. *((unsigned long *)&ras_log_buf), status, state);
  112. /* format and print the extended information */
  113. log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);
  114. spin_unlock(&ras_log_buf_lock);
  115. return IRQ_HANDLED;
  116. }
  117. /*
  118. * Handle hardware error interrupts.
  119. *
  120. * RTAS check-exception is called to collect data on the exception. If
  121. * the error is deemed recoverable, we log a warning and return.
  122. * For nonrecoverable errors, an error is logged and we stop all processing
  123. * as quickly as possible in order to prevent propagation of the failure.
  124. */
  125. static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
  126. {
  127. struct rtas_error_log *rtas_elog;
  128. int status = 0xdeadbeef;
  129. int fatal;
  130. spin_lock(&ras_log_buf_lock);
  131. status = rtas_call(ras_check_exception_token, 6, 1, NULL,
  132. RTAS_VECTOR_EXTERNAL_INTERRUPT,
  133. irq_map[irq].hwirq,
  134. RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
  135. __pa(&ras_log_buf),
  136. rtas_get_error_log_max());
  137. rtas_elog = (struct rtas_error_log *)ras_log_buf;
  138. if ((status == 0) && (rtas_elog->severity >= RTAS_SEVERITY_ERROR_SYNC))
  139. fatal = 1;
  140. else
  141. fatal = 0;
  142. /* format and print the extended information */
  143. log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, fatal);
  144. if (fatal) {
  145. udbg_printf("Fatal HW Error <0x%lx 0x%x>\n",
  146. *((unsigned long *)&ras_log_buf), status);
  147. printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
  148. *((unsigned long *)&ras_log_buf), status);
  149. #ifndef DEBUG_RTAS_POWER_OFF
  150. /* Don't actually power off when debugging so we can test
  151. * without actually failing while injecting errors.
  152. * Error data will not be logged to syslog.
  153. */
  154. ppc_md.power_off();
  155. #endif
  156. } else {
  157. udbg_printf("Recoverable HW Error <0x%lx 0x%x>\n",
  158. *((unsigned long *)&ras_log_buf), status);
  159. printk(KERN_WARNING
  160. "Warning: Recoverable hardware error <0x%lx 0x%x>\n",
  161. *((unsigned long *)&ras_log_buf), status);
  162. }
  163. spin_unlock(&ras_log_buf_lock);
  164. return IRQ_HANDLED;
  165. }
  166. /* Get the error information for errors coming through the
  167. * FWNMI vectors. The pt_regs' r3 will be updated to reflect
  168. * the actual r3 if possible, and a ptr to the error log entry
  169. * will be returned if found.
  170. *
  171. * The mce_data_buf does not have any locks or protection around it,
  172. * if a second machine check comes in, or a system reset is done
  173. * before we have logged the error, then we will get corruption in the
  174. * error log. This is preferable over holding off on calling
  175. * ibm,nmi-interlock which would result in us checkstopping if a
  176. * second machine check did come in.
  177. */
  178. static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
  179. {
  180. unsigned long errdata = regs->gpr[3];
  181. struct rtas_error_log *errhdr = NULL;
  182. unsigned long *savep;
  183. if ((errdata >= 0x7000 && errdata < 0x7fff0) ||
  184. (errdata >= rtas.base && errdata < rtas.base + rtas.size - 16)) {
  185. savep = __va(errdata);
  186. regs->gpr[3] = savep[0]; /* restore original r3 */
  187. memset(mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
  188. memcpy(mce_data_buf, (char *)(savep + 1), RTAS_ERROR_LOG_MAX);
  189. errhdr = (struct rtas_error_log *)mce_data_buf;
  190. } else {
  191. printk("FWNMI: corrupt r3\n");
  192. }
  193. return errhdr;
  194. }
  195. /* Call this when done with the data returned by FWNMI_get_errinfo.
  196. * It will release the saved data area for other CPUs in the
  197. * partition to receive FWNMI errors.
  198. */
  199. static void fwnmi_release_errinfo(void)
  200. {
  201. int ret = rtas_call(rtas_token("ibm,nmi-interlock"), 0, 1, NULL);
  202. if (ret != 0)
  203. printk("FWNMI: nmi-interlock failed: %d\n", ret);
  204. }
  205. int pSeries_system_reset_exception(struct pt_regs *regs)
  206. {
  207. if (fwnmi_active) {
  208. struct rtas_error_log *errhdr = fwnmi_get_errinfo(regs);
  209. if (errhdr) {
  210. /* XXX Should look at FWNMI information */
  211. }
  212. fwnmi_release_errinfo();
  213. }
  214. return 0; /* need to perform reset */
  215. }
  216. /*
  217. * See if we can recover from a machine check exception.
  218. * This is only called on power4 (or above) and only via
  219. * the Firmware Non-Maskable Interrupts (fwnmi) handler
  220. * which provides the error analysis for us.
  221. *
  222. * Return 1 if corrected (or delivered a signal).
  223. * Return 0 if there is nothing we can do.
  224. */
  225. static int recover_mce(struct pt_regs *regs, struct rtas_error_log * err)
  226. {
  227. int nonfatal = 0;
  228. if (err->disposition == RTAS_DISP_FULLY_RECOVERED) {
  229. /* Platform corrected itself */
  230. nonfatal = 1;
  231. } else if ((regs->msr & MSR_RI) &&
  232. user_mode(regs) &&
  233. err->severity == RTAS_SEVERITY_ERROR_SYNC &&
  234. err->disposition == RTAS_DISP_NOT_RECOVERED &&
  235. err->target == RTAS_TARGET_MEMORY &&
  236. err->type == RTAS_TYPE_ECC_UNCORR &&
  237. !(current->pid == 0 || is_global_init(current))) {
  238. /* Kill off a user process with an ECC error */
  239. printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
  240. current->pid);
  241. /* XXX something better for ECC error? */
  242. _exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
  243. nonfatal = 1;
  244. }
  245. log_error((char *)err, ERR_TYPE_RTAS_LOG, !nonfatal);
  246. return nonfatal;
  247. }
  248. /*
  249. * Handle a machine check.
  250. *
  251. * Note that on Power 4 and beyond Firmware Non-Maskable Interrupts (fwnmi)
  252. * should be present. If so the handler which called us tells us if the
  253. * error was recovered (never true if RI=0).
  254. *
  255. * On hardware prior to Power 4 these exceptions were asynchronous which
  256. * means we can't tell exactly where it occurred and so we can't recover.
  257. */
  258. int pSeries_machine_check_exception(struct pt_regs *regs)
  259. {
  260. struct rtas_error_log *errp;
  261. if (fwnmi_active) {
  262. errp = fwnmi_get_errinfo(regs);
  263. fwnmi_release_errinfo();
  264. if (errp && recover_mce(regs, errp))
  265. return 1;
  266. }
  267. return 0;
  268. }