einj.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /*
  2. * APEI Error INJection support
  3. *
  4. * EINJ provides a hardware error injection mechanism, this is useful
  5. * for debugging and testing of other APEI and RAS features.
  6. *
  7. * For more information about EINJ, please refer to ACPI Specification
  8. * version 4.0, section 17.5.
  9. *
  10. * Copyright 2009 Intel Corp.
  11. * Author: Huang Ying <ying.huang@intel.com>
  12. *
  13. * This program is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU General Public License version
  15. * 2 as published by the Free Software Foundation.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  25. */
  26. #include <linux/kernel.h>
  27. #include <linux/module.h>
  28. #include <linux/init.h>
  29. #include <linux/io.h>
  30. #include <linux/debugfs.h>
  31. #include <linux/seq_file.h>
  32. #include <linux/nmi.h>
  33. #include <linux/delay.h>
  34. #include <acpi/acpi.h>
  35. #include "apei-internal.h"
  36. #define EINJ_PFX "EINJ: "
  37. #define SPIN_UNIT 100 /* 100ns */
  38. /* Firmware should respond within 1 miliseconds */
  39. #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC)
  40. #define EINJ_OP_BUSY 0x1
  41. #define EINJ_STATUS_SUCCESS 0x0
  42. #define EINJ_STATUS_FAIL 0x1
  43. #define EINJ_STATUS_INVAL 0x2
  44. #define EINJ_TAB_ENTRY(tab) \
  45. ((struct acpi_whea_header *)((char *)(tab) + \
  46. sizeof(struct acpi_table_einj)))
  47. static struct acpi_table_einj *einj_tab;
  48. static struct apei_resources einj_resources;
  49. static struct apei_exec_ins_type einj_ins_type[] = {
  50. [ACPI_EINJ_READ_REGISTER] = {
  51. .flags = APEI_EXEC_INS_ACCESS_REGISTER,
  52. .run = apei_exec_read_register,
  53. },
  54. [ACPI_EINJ_READ_REGISTER_VALUE] = {
  55. .flags = APEI_EXEC_INS_ACCESS_REGISTER,
  56. .run = apei_exec_read_register_value,
  57. },
  58. [ACPI_EINJ_WRITE_REGISTER] = {
  59. .flags = APEI_EXEC_INS_ACCESS_REGISTER,
  60. .run = apei_exec_write_register,
  61. },
  62. [ACPI_EINJ_WRITE_REGISTER_VALUE] = {
  63. .flags = APEI_EXEC_INS_ACCESS_REGISTER,
  64. .run = apei_exec_write_register_value,
  65. },
  66. [ACPI_EINJ_NOOP] = {
  67. .flags = 0,
  68. .run = apei_exec_noop,
  69. },
  70. };
  71. /*
  72. * Prevent EINJ interpreter to run simultaneously, because the
  73. * corresponding firmware implementation may not work properly when
  74. * invoked simultaneously.
  75. */
  76. static DEFINE_MUTEX(einj_mutex);
  77. static void einj_exec_ctx_init(struct apei_exec_context *ctx)
  78. {
  79. apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type),
  80. EINJ_TAB_ENTRY(einj_tab), einj_tab->entries);
  81. }
  82. static int __einj_get_available_error_type(u32 *type)
  83. {
  84. struct apei_exec_context ctx;
  85. int rc;
  86. einj_exec_ctx_init(&ctx);
  87. rc = apei_exec_run(&ctx, ACPI_EINJ_GET_ERROR_TYPE);
  88. if (rc)
  89. return rc;
  90. *type = apei_exec_ctx_get_output(&ctx);
  91. return 0;
  92. }
  93. /* Get error injection capabilities of the platform */
  94. static int einj_get_available_error_type(u32 *type)
  95. {
  96. int rc;
  97. mutex_lock(&einj_mutex);
  98. rc = __einj_get_available_error_type(type);
  99. mutex_unlock(&einj_mutex);
  100. return rc;
  101. }
  102. static int einj_timedout(u64 *t)
  103. {
  104. if ((s64)*t < SPIN_UNIT) {
  105. pr_warning(FW_WARN EINJ_PFX
  106. "Firmware does not respond in time\n");
  107. return 1;
  108. }
  109. *t -= SPIN_UNIT;
  110. ndelay(SPIN_UNIT);
  111. touch_nmi_watchdog();
  112. return 0;
  113. }
  114. /* do sanity check to trigger table */
  115. static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab)
  116. {
  117. if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger))
  118. return -EINVAL;
  119. if (trigger_tab->table_size > PAGE_SIZE ||
  120. trigger_tab->table_size <= trigger_tab->header_size)
  121. return -EINVAL;
  122. if (trigger_tab->entry_count !=
  123. (trigger_tab->table_size - trigger_tab->header_size) /
  124. sizeof(struct acpi_einj_entry))
  125. return -EINVAL;
  126. return 0;
  127. }
  128. /* Execute instructions in trigger error action table */
  129. static int __einj_error_trigger(u64 trigger_paddr)
  130. {
  131. struct acpi_einj_trigger *trigger_tab = NULL;
  132. struct apei_exec_context trigger_ctx;
  133. struct apei_resources trigger_resources;
  134. struct acpi_whea_header *trigger_entry;
  135. struct resource *r;
  136. u32 table_size;
  137. int rc = -EIO;
  138. r = request_mem_region(trigger_paddr, sizeof(*trigger_tab),
  139. "APEI EINJ Trigger Table");
  140. if (!r) {
  141. pr_err(EINJ_PFX
  142. "Can not request iomem region <%016llx-%016llx> for Trigger table.\n",
  143. (unsigned long long)trigger_paddr,
  144. (unsigned long long)trigger_paddr+sizeof(*trigger_tab));
  145. goto out;
  146. }
  147. trigger_tab = ioremap_cache(trigger_paddr, sizeof(*trigger_tab));
  148. if (!trigger_tab) {
  149. pr_err(EINJ_PFX "Failed to map trigger table!\n");
  150. goto out_rel_header;
  151. }
  152. rc = einj_check_trigger_header(trigger_tab);
  153. if (rc) {
  154. pr_warning(FW_BUG EINJ_PFX
  155. "The trigger error action table is invalid\n");
  156. goto out_rel_header;
  157. }
  158. rc = -EIO;
  159. table_size = trigger_tab->table_size;
  160. r = request_mem_region(trigger_paddr + sizeof(*trigger_tab),
  161. table_size - sizeof(*trigger_tab),
  162. "APEI EINJ Trigger Table");
  163. if (!r) {
  164. pr_err(EINJ_PFX
  165. "Can not request iomem region <%016llx-%016llx> for Trigger Table Entry.\n",
  166. (unsigned long long)trigger_paddr+sizeof(*trigger_tab),
  167. (unsigned long long)trigger_paddr + table_size);
  168. goto out_rel_header;
  169. }
  170. iounmap(trigger_tab);
  171. trigger_tab = ioremap_cache(trigger_paddr, table_size);
  172. if (!trigger_tab) {
  173. pr_err(EINJ_PFX "Failed to map trigger table!\n");
  174. goto out_rel_entry;
  175. }
  176. trigger_entry = (struct acpi_whea_header *)
  177. ((char *)trigger_tab + sizeof(struct acpi_einj_trigger));
  178. apei_resources_init(&trigger_resources);
  179. apei_exec_ctx_init(&trigger_ctx, einj_ins_type,
  180. ARRAY_SIZE(einj_ins_type),
  181. trigger_entry, trigger_tab->entry_count);
  182. rc = apei_exec_collect_resources(&trigger_ctx, &trigger_resources);
  183. if (rc)
  184. goto out_fini;
  185. rc = apei_resources_sub(&trigger_resources, &einj_resources);
  186. if (rc)
  187. goto out_fini;
  188. rc = apei_resources_request(&trigger_resources, "APEI EINJ Trigger");
  189. if (rc)
  190. goto out_fini;
  191. rc = apei_exec_pre_map_gars(&trigger_ctx);
  192. if (rc)
  193. goto out_release;
  194. rc = apei_exec_run(&trigger_ctx, ACPI_EINJ_TRIGGER_ERROR);
  195. apei_exec_post_unmap_gars(&trigger_ctx);
  196. out_release:
  197. apei_resources_release(&trigger_resources);
  198. out_fini:
  199. apei_resources_fini(&trigger_resources);
  200. out_rel_entry:
  201. release_mem_region(trigger_paddr + sizeof(*trigger_tab),
  202. table_size - sizeof(*trigger_tab));
  203. out_rel_header:
  204. release_mem_region(trigger_paddr, sizeof(*trigger_tab));
  205. out:
  206. if (trigger_tab)
  207. iounmap(trigger_tab);
  208. return rc;
  209. }
  210. static int __einj_error_inject(u32 type)
  211. {
  212. struct apei_exec_context ctx;
  213. u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT;
  214. int rc;
  215. einj_exec_ctx_init(&ctx);
  216. rc = apei_exec_run(&ctx, ACPI_EINJ_BEGIN_OPERATION);
  217. if (rc)
  218. return rc;
  219. apei_exec_ctx_set_input(&ctx, type);
  220. rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE);
  221. if (rc)
  222. return rc;
  223. rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION);
  224. if (rc)
  225. return rc;
  226. for (;;) {
  227. rc = apei_exec_run(&ctx, ACPI_EINJ_CHECK_BUSY_STATUS);
  228. if (rc)
  229. return rc;
  230. val = apei_exec_ctx_get_output(&ctx);
  231. if (!(val & EINJ_OP_BUSY))
  232. break;
  233. if (einj_timedout(&timeout))
  234. return -EIO;
  235. }
  236. rc = apei_exec_run(&ctx, ACPI_EINJ_GET_COMMAND_STATUS);
  237. if (rc)
  238. return rc;
  239. val = apei_exec_ctx_get_output(&ctx);
  240. if (val != EINJ_STATUS_SUCCESS)
  241. return -EBUSY;
  242. rc = apei_exec_run(&ctx, ACPI_EINJ_GET_TRIGGER_TABLE);
  243. if (rc)
  244. return rc;
  245. trigger_paddr = apei_exec_ctx_get_output(&ctx);
  246. rc = __einj_error_trigger(trigger_paddr);
  247. if (rc)
  248. return rc;
  249. rc = apei_exec_run(&ctx, ACPI_EINJ_END_OPERATION);
  250. return rc;
  251. }
  252. /* Inject the specified hardware error */
  253. static int einj_error_inject(u32 type)
  254. {
  255. int rc;
  256. mutex_lock(&einj_mutex);
  257. rc = __einj_error_inject(type);
  258. mutex_unlock(&einj_mutex);
  259. return rc;
  260. }
  261. static u32 error_type;
  262. static struct dentry *einj_debug_dir;
  263. static int available_error_type_show(struct seq_file *m, void *v)
  264. {
  265. int rc;
  266. u32 available_error_type = 0;
  267. rc = einj_get_available_error_type(&available_error_type);
  268. if (rc)
  269. return rc;
  270. if (available_error_type & 0x0001)
  271. seq_printf(m, "0x00000001\tProcessor Correctable\n");
  272. if (available_error_type & 0x0002)
  273. seq_printf(m, "0x00000002\tProcessor Uncorrectable non-fatal\n");
  274. if (available_error_type & 0x0004)
  275. seq_printf(m, "0x00000004\tProcessor Uncorrectable fatal\n");
  276. if (available_error_type & 0x0008)
  277. seq_printf(m, "0x00000008\tMemory Correctable\n");
  278. if (available_error_type & 0x0010)
  279. seq_printf(m, "0x00000010\tMemory Uncorrectable non-fatal\n");
  280. if (available_error_type & 0x0020)
  281. seq_printf(m, "0x00000020\tMemory Uncorrectable fatal\n");
  282. if (available_error_type & 0x0040)
  283. seq_printf(m, "0x00000040\tPCI Express Correctable\n");
  284. if (available_error_type & 0x0080)
  285. seq_printf(m, "0x00000080\tPCI Express Uncorrectable non-fatal\n");
  286. if (available_error_type & 0x0100)
  287. seq_printf(m, "0x00000100\tPCI Express Uncorrectable fatal\n");
  288. if (available_error_type & 0x0200)
  289. seq_printf(m, "0x00000200\tPlatform Correctable\n");
  290. if (available_error_type & 0x0400)
  291. seq_printf(m, "0x00000400\tPlatform Uncorrectable non-fatal\n");
  292. if (available_error_type & 0x0800)
  293. seq_printf(m, "0x00000800\tPlatform Uncorrectable fatal\n");
  294. return 0;
  295. }
  296. static int available_error_type_open(struct inode *inode, struct file *file)
  297. {
  298. return single_open(file, available_error_type_show, NULL);
  299. }
  300. static const struct file_operations available_error_type_fops = {
  301. .open = available_error_type_open,
  302. .read = seq_read,
  303. .llseek = seq_lseek,
  304. .release = single_release,
  305. };
  306. static int error_type_get(void *data, u64 *val)
  307. {
  308. *val = error_type;
  309. return 0;
  310. }
  311. static int error_type_set(void *data, u64 val)
  312. {
  313. int rc;
  314. u32 available_error_type = 0;
  315. /* Only one error type can be specified */
  316. if (val & (val - 1))
  317. return -EINVAL;
  318. rc = einj_get_available_error_type(&available_error_type);
  319. if (rc)
  320. return rc;
  321. if (!(val & available_error_type))
  322. return -EINVAL;
  323. error_type = val;
  324. return 0;
  325. }
  326. DEFINE_SIMPLE_ATTRIBUTE(error_type_fops, error_type_get,
  327. error_type_set, "0x%llx\n");
  328. static int error_inject_set(void *data, u64 val)
  329. {
  330. if (!error_type)
  331. return -EINVAL;
  332. return einj_error_inject(error_type);
  333. }
  334. DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL,
  335. error_inject_set, "%llu\n");
  336. static int einj_check_table(struct acpi_table_einj *einj_tab)
  337. {
  338. if (einj_tab->header_length != sizeof(struct acpi_table_einj))
  339. return -EINVAL;
  340. if (einj_tab->header.length < sizeof(struct acpi_table_einj))
  341. return -EINVAL;
  342. if (einj_tab->entries !=
  343. (einj_tab->header.length - sizeof(struct acpi_table_einj)) /
  344. sizeof(struct acpi_einj_entry))
  345. return -EINVAL;
  346. return 0;
  347. }
  348. static int __init einj_init(void)
  349. {
  350. int rc;
  351. acpi_status status;
  352. struct dentry *fentry;
  353. struct apei_exec_context ctx;
  354. if (acpi_disabled)
  355. return -ENODEV;
  356. status = acpi_get_table(ACPI_SIG_EINJ, 0,
  357. (struct acpi_table_header **)&einj_tab);
  358. if (status == AE_NOT_FOUND) {
  359. pr_info(EINJ_PFX "Table is not found!\n");
  360. return -ENODEV;
  361. } else if (ACPI_FAILURE(status)) {
  362. const char *msg = acpi_format_exception(status);
  363. pr_err(EINJ_PFX "Failed to get table, %s\n", msg);
  364. return -EINVAL;
  365. }
  366. rc = einj_check_table(einj_tab);
  367. if (rc) {
  368. pr_warning(FW_BUG EINJ_PFX "EINJ table is invalid\n");
  369. return -EINVAL;
  370. }
  371. rc = -ENOMEM;
  372. einj_debug_dir = debugfs_create_dir("einj", apei_get_debugfs_dir());
  373. if (!einj_debug_dir)
  374. goto err_cleanup;
  375. fentry = debugfs_create_file("available_error_type", S_IRUSR,
  376. einj_debug_dir, NULL,
  377. &available_error_type_fops);
  378. if (!fentry)
  379. goto err_cleanup;
  380. fentry = debugfs_create_file("error_type", S_IRUSR | S_IWUSR,
  381. einj_debug_dir, NULL, &error_type_fops);
  382. if (!fentry)
  383. goto err_cleanup;
  384. fentry = debugfs_create_file("error_inject", S_IWUSR,
  385. einj_debug_dir, NULL, &error_inject_fops);
  386. if (!fentry)
  387. goto err_cleanup;
  388. apei_resources_init(&einj_resources);
  389. einj_exec_ctx_init(&ctx);
  390. rc = apei_exec_collect_resources(&ctx, &einj_resources);
  391. if (rc)
  392. goto err_fini;
  393. rc = apei_resources_request(&einj_resources, "APEI EINJ");
  394. if (rc)
  395. goto err_fini;
  396. rc = apei_exec_pre_map_gars(&ctx);
  397. if (rc)
  398. goto err_release;
  399. pr_info(EINJ_PFX "Error INJection is initialized.\n");
  400. return 0;
  401. err_release:
  402. apei_resources_release(&einj_resources);
  403. err_fini:
  404. apei_resources_fini(&einj_resources);
  405. err_cleanup:
  406. debugfs_remove_recursive(einj_debug_dir);
  407. return rc;
  408. }
  409. static void __exit einj_exit(void)
  410. {
  411. struct apei_exec_context ctx;
  412. einj_exec_ctx_init(&ctx);
  413. apei_exec_post_unmap_gars(&ctx);
  414. apei_resources_release(&einj_resources);
  415. apei_resources_fini(&einj_resources);
  416. debugfs_remove_recursive(einj_debug_dir);
  417. }
  418. module_init(einj_init);
  419. module_exit(einj_exit);
  420. MODULE_AUTHOR("Huang Ying");
  421. MODULE_DESCRIPTION("APEI Error INJection support");
  422. MODULE_LICENSE("GPL");