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-2010 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 27 #include <linux/kernel.h> 28 #include <linux/module.h> 29 #include <linux/init.h> 30 #include <linux/io.h> 31 #include <linux/debugfs.h> 32 #include <linux/seq_file.h> 33 #include <linux/nmi.h> 34 #include <linux/delay.h> 35 #include <acpi/acpi.h> 36 37 #include "apei-internal.h" 38 39 #define EINJ_PFX "EINJ: " 40 41 #define SPIN_UNIT 100 /* 100ns */ 42 /* Firmware should respond within 1 milliseconds */ 43 #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) 44 45 /* 46 * Some BIOSes allow parameters to the SET_ERROR_TYPE entries in the 47 * EINJ table through an unpublished extension. Use with caution as 48 * most will ignore the parameter and make their own choice of address 49 * for error injection. 50 */ 51 struct einj_parameter { 52 u64 type; 53 u64 reserved1; 54 u64 reserved2; 55 u64 param1; 56 u64 param2; 57 }; 58 59 #define EINJ_OP_BUSY 0x1 60 #define EINJ_STATUS_SUCCESS 0x0 61 #define EINJ_STATUS_FAIL 0x1 62 #define EINJ_STATUS_INVAL 0x2 63 64 #define EINJ_TAB_ENTRY(tab) \ 65 ((struct acpi_whea_header *)((char *)(tab) + \ 66 sizeof(struct acpi_table_einj))) 67 68 static struct acpi_table_einj *einj_tab; 69 70 static struct apei_resources einj_resources; 71 72 static struct apei_exec_ins_type einj_ins_type[] = { 73 [ACPI_EINJ_READ_REGISTER] = { 74 .flags = APEI_EXEC_INS_ACCESS_REGISTER, 75 .run = apei_exec_read_register, 76 }, 77 [ACPI_EINJ_READ_REGISTER_VALUE] = { 78 .flags = APEI_EXEC_INS_ACCESS_REGISTER, 79 .run = apei_exec_read_register_value, 80 }, 81 [ACPI_EINJ_WRITE_REGISTER] = { 82 .flags = APEI_EXEC_INS_ACCESS_REGISTER, 83 .run = apei_exec_write_register, 84 }, 85 [ACPI_EINJ_WRITE_REGISTER_VALUE] = { 86 .flags = APEI_EXEC_INS_ACCESS_REGISTER, 87 .run = apei_exec_write_register_value, 88 }, 89 [ACPI_EINJ_NOOP] = { 90 .flags = 0, 91 .run = apei_exec_noop, 92 }, 93 }; 94 95 /* 96 * Prevent EINJ interpreter to run simultaneously, because the 97 * corresponding firmware implementation may not work properly when 98 * invoked simultaneously. 99 */ 100 static DEFINE_MUTEX(einj_mutex); 101 102 static struct einj_parameter *einj_param; 103 104 static void einj_exec_ctx_init(struct apei_exec_context *ctx) 105 { 106 apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type), 107 EINJ_TAB_ENTRY(einj_tab), einj_tab->entries); 108 } 109 110 static int __einj_get_available_error_type(u32 *type) 111 { 112 struct apei_exec_context ctx; 113 int rc; 114 115 einj_exec_ctx_init(&ctx); 116 rc = apei_exec_run(&ctx, ACPI_EINJ_GET_ERROR_TYPE); 117 if (rc) 118 return rc; 119 *type = apei_exec_ctx_get_output(&ctx); 120 121 return 0; 122 } 123 124 /* Get error injection capabilities of the platform */ 125 static int einj_get_available_error_type(u32 *type) 126 { 127 int rc; 128 129 mutex_lock(&einj_mutex); 130 rc = __einj_get_available_error_type(type); 131 mutex_unlock(&einj_mutex); 132 133 return rc; 134 } 135 136 static int einj_timedout(u64 *t) 137 { 138 if ((s64)*t < SPIN_UNIT) { 139 pr_warning(FW_WARN EINJ_PFX 140 "Firmware does not respond in time\n"); 141 return 1; 142 } 143 *t -= SPIN_UNIT; 144 ndelay(SPIN_UNIT); 145 touch_nmi_watchdog(); 146 return 0; 147 } 148 149 static u64 einj_get_parameter_address(void) 150 { 151 int i; 152 u64 paddr = 0; 153 struct acpi_whea_header *entry; 154 155 entry = EINJ_TAB_ENTRY(einj_tab); 156 for (i = 0; i < einj_tab->entries; i++) { 157 if (entry->action == ACPI_EINJ_SET_ERROR_TYPE && 158 entry->instruction == ACPI_EINJ_WRITE_REGISTER && 159 entry->register_region.space_id == 160 ACPI_ADR_SPACE_SYSTEM_MEMORY) 161 memcpy(&paddr, &entry->register_region.address, 162 sizeof(paddr)); 163 entry++; 164 } 165 166 return paddr; 167 } 168 169 /* do sanity check to trigger table */ 170 static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab) 171 { 172 if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger)) 173 return -EINVAL; 174 if (trigger_tab->table_size > PAGE_SIZE || 175 trigger_tab->table_size <= trigger_tab->header_size) 176 return -EINVAL; 177 if (trigger_tab->entry_count != 178 (trigger_tab->table_size - trigger_tab->header_size) / 179 sizeof(struct acpi_einj_entry)) 180 return -EINVAL; 181 182 return 0; 183 } 184 185 /* Execute instructions in trigger error action table */ 186 static int __einj_error_trigger(u64 trigger_paddr) 187 { 188 struct acpi_einj_trigger *trigger_tab = NULL; 189 struct apei_exec_context trigger_ctx; 190 struct apei_resources trigger_resources; 191 struct acpi_whea_header *trigger_entry; 192 struct resource *r; 193 u32 table_size; 194 int rc = -EIO; 195 196 r = request_mem_region(trigger_paddr, sizeof(*trigger_tab), 197 "APEI EINJ Trigger Table"); 198 if (!r) { 199 pr_err(EINJ_PFX 200 "Can not request iomem region <%016llx-%016llx> for Trigger table.\n", 201 (unsigned long long)trigger_paddr, 202 (unsigned long long)trigger_paddr+sizeof(*trigger_tab)); 203 goto out; 204 } 205 trigger_tab = ioremap_cache(trigger_paddr, sizeof(*trigger_tab)); 206 if (!trigger_tab) { 207 pr_err(EINJ_PFX "Failed to map trigger table!\n"); 208 goto out_rel_header; 209 } 210 rc = einj_check_trigger_header(trigger_tab); 211 if (rc) { 212 pr_warning(FW_BUG EINJ_PFX 213 "The trigger error action table is invalid\n"); 214 goto out_rel_header; 215 } 216 rc = -EIO; 217 table_size = trigger_tab->table_size; 218 r = request_mem_region(trigger_paddr + sizeof(*trigger_tab), 219 table_size - sizeof(*trigger_tab), 220 "APEI EINJ Trigger Table"); 221 if (!r) { 222 pr_err(EINJ_PFX 223 "Can not request iomem region <%016llx-%016llx> for Trigger Table Entry.\n", 224 (unsigned long long)trigger_paddr+sizeof(*trigger_tab), 225 (unsigned long long)trigger_paddr + table_size); 226 goto out_rel_header; 227 } 228 iounmap(trigger_tab); 229 trigger_tab = ioremap_cache(trigger_paddr, table_size); 230 if (!trigger_tab) { 231 pr_err(EINJ_PFX "Failed to map trigger table!\n"); 232 goto out_rel_entry; 233 } 234 trigger_entry = (struct acpi_whea_header *) 235 ((char *)trigger_tab + sizeof(struct acpi_einj_trigger)); 236 apei_resources_init(&trigger_resources); 237 apei_exec_ctx_init(&trigger_ctx, einj_ins_type, 238 ARRAY_SIZE(einj_ins_type), 239 trigger_entry, trigger_tab->entry_count); 240 rc = apei_exec_collect_resources(&trigger_ctx, &trigger_resources); 241 if (rc) 242 goto out_fini; 243 rc = apei_resources_sub(&trigger_resources, &einj_resources); 244 if (rc) 245 goto out_fini; 246 rc = apei_resources_request(&trigger_resources, "APEI EINJ Trigger"); 247 if (rc) 248 goto out_fini; 249 rc = apei_exec_pre_map_gars(&trigger_ctx); 250 if (rc) 251 goto out_release; 252 253 rc = apei_exec_run(&trigger_ctx, ACPI_EINJ_TRIGGER_ERROR); 254 255 apei_exec_post_unmap_gars(&trigger_ctx); 256 out_release: 257 apei_resources_release(&trigger_resources); 258 out_fini: 259 apei_resources_fini(&trigger_resources); 260 out_rel_entry: 261 release_mem_region(trigger_paddr + sizeof(*trigger_tab), 262 table_size - sizeof(*trigger_tab)); 263 out_rel_header: 264 release_mem_region(trigger_paddr, sizeof(*trigger_tab)); 265 out: 266 if (trigger_tab) 267 iounmap(trigger_tab); 268 269 return rc; 270 } 271 272 static int __einj_error_inject(u32 type, u64 param1, u64 param2) 273 { 274 struct apei_exec_context ctx; 275 u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT; 276 int rc; 277 278 einj_exec_ctx_init(&ctx); 279 280 rc = apei_exec_run(&ctx, ACPI_EINJ_BEGIN_OPERATION); 281 if (rc) 282 return rc; 283 apei_exec_ctx_set_input(&ctx, type); 284 rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE); 285 if (rc) 286 return rc; 287 if (einj_param) { 288 writeq(param1, &einj_param->param1); 289 writeq(param2, &einj_param->param2); 290 } 291 rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION); 292 if (rc) 293 return rc; 294 for (;;) { 295 rc = apei_exec_run(&ctx, ACPI_EINJ_CHECK_BUSY_STATUS); 296 if (rc) 297 return rc; 298 val = apei_exec_ctx_get_output(&ctx); 299 if (!(val & EINJ_OP_BUSY)) 300 break; 301 if (einj_timedout(&timeout)) 302 return -EIO; 303 } 304 rc = apei_exec_run(&ctx, ACPI_EINJ_GET_COMMAND_STATUS); 305 if (rc) 306 return rc; 307 val = apei_exec_ctx_get_output(&ctx); 308 if (val != EINJ_STATUS_SUCCESS) 309 return -EBUSY; 310 311 rc = apei_exec_run(&ctx, ACPI_EINJ_GET_TRIGGER_TABLE); 312 if (rc) 313 return rc; 314 trigger_paddr = apei_exec_ctx_get_output(&ctx); 315 rc = __einj_error_trigger(trigger_paddr); 316 if (rc) 317 return rc; 318 rc = apei_exec_run(&ctx, ACPI_EINJ_END_OPERATION); 319 320 return rc; 321 } 322 323 /* Inject the specified hardware error */ 324 static int einj_error_inject(u32 type, u64 param1, u64 param2) 325 { 326 int rc; 327 328 mutex_lock(&einj_mutex); 329 rc = __einj_error_inject(type, param1, param2); 330 mutex_unlock(&einj_mutex); 331 332 return rc; 333 } 334 335 static u32 error_type; 336 static u64 error_param1; 337 static u64 error_param2; 338 static struct dentry *einj_debug_dir; 339 340 static int available_error_type_show(struct seq_file *m, void *v) 341 { 342 int rc; 343 u32 available_error_type = 0; 344 345 rc = einj_get_available_error_type(&available_error_type); 346 if (rc) 347 return rc; 348 if (available_error_type & 0x0001) 349 seq_printf(m, "0x00000001\tProcessor Correctable\n"); 350 if (available_error_type & 0x0002) 351 seq_printf(m, "0x00000002\tProcessor Uncorrectable non-fatal\n"); 352 if (available_error_type & 0x0004) 353 seq_printf(m, "0x00000004\tProcessor Uncorrectable fatal\n"); 354 if (available_error_type & 0x0008) 355 seq_printf(m, "0x00000008\tMemory Correctable\n"); 356 if (available_error_type & 0x0010) 357 seq_printf(m, "0x00000010\tMemory Uncorrectable non-fatal\n"); 358 if (available_error_type & 0x0020) 359 seq_printf(m, "0x00000020\tMemory Uncorrectable fatal\n"); 360 if (available_error_type & 0x0040) 361 seq_printf(m, "0x00000040\tPCI Express Correctable\n"); 362 if (available_error_type & 0x0080) 363 seq_printf(m, "0x00000080\tPCI Express Uncorrectable non-fatal\n"); 364 if (available_error_type & 0x0100) 365 seq_printf(m, "0x00000100\tPCI Express Uncorrectable fatal\n"); 366 if (available_error_type & 0x0200) 367 seq_printf(m, "0x00000200\tPlatform Correctable\n"); 368 if (available_error_type & 0x0400) 369 seq_printf(m, "0x00000400\tPlatform Uncorrectable non-fatal\n"); 370 if (available_error_type & 0x0800) 371 seq_printf(m, "0x00000800\tPlatform Uncorrectable fatal\n"); 372 373 return 0; 374 } 375 376 static int available_error_type_open(struct inode *inode, struct file *file) 377 { 378 return single_open(file, available_error_type_show, NULL); 379 } 380 381 static const struct file_operations available_error_type_fops = { 382 .open = available_error_type_open, 383 .read = seq_read, 384 .llseek = seq_lseek, 385 .release = single_release, 386 }; 387 388 static int error_type_get(void *data, u64 *val) 389 { 390 *val = error_type; 391 392 return 0; 393 } 394 395 static int error_type_set(void *data, u64 val) 396 { 397 int rc; 398 u32 available_error_type = 0; 399 400 /* Only one error type can be specified */ 401 if (val & (val - 1)) 402 return -EINVAL; 403 rc = einj_get_available_error_type(&available_error_type); 404 if (rc) 405 return rc; 406 if (!(val & available_error_type)) 407 return -EINVAL; 408 error_type = val; 409 410 return 0; 411 } 412 413 DEFINE_SIMPLE_ATTRIBUTE(error_type_fops, error_type_get, 414 error_type_set, "0x%llx\n"); 415 416 static int error_inject_set(void *data, u64 val) 417 { 418 if (!error_type) 419 return -EINVAL; 420 421 return einj_error_inject(error_type, error_param1, error_param2); 422 } 423 424 DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, 425 error_inject_set, "%llu\n"); 426 427 static int einj_check_table(struct acpi_table_einj *einj_tab) 428 { 429 if ((einj_tab->header_length != 430 (sizeof(struct acpi_table_einj) - sizeof(einj_tab->header))) 431 && (einj_tab->header_length != sizeof(struct acpi_table_einj))) 432 return -EINVAL; 433 if (einj_tab->header.length < sizeof(struct acpi_table_einj)) 434 return -EINVAL; 435 if (einj_tab->entries != 436 (einj_tab->header.length - sizeof(struct acpi_table_einj)) / 437 sizeof(struct acpi_einj_entry)) 438 return -EINVAL; 439 440 return 0; 441 } 442 443 static int __init einj_init(void) 444 { 445 int rc; 446 u64 param_paddr; 447 acpi_status status; 448 struct dentry *fentry; 449 struct apei_exec_context ctx; 450 451 if (acpi_disabled) 452 return -ENODEV; 453 454 status = acpi_get_table(ACPI_SIG_EINJ, 0, 455 (struct acpi_table_header **)&einj_tab); 456 if (status == AE_NOT_FOUND) { 457 pr_info(EINJ_PFX "Table is not found!\n"); 458 return -ENODEV; 459 } else if (ACPI_FAILURE(status)) { 460 const char *msg = acpi_format_exception(status); 461 pr_err(EINJ_PFX "Failed to get table, %s\n", msg); 462 return -EINVAL; 463 } 464 465 rc = einj_check_table(einj_tab); 466 if (rc) { 467 pr_warning(FW_BUG EINJ_PFX "EINJ table is invalid\n"); 468 return -EINVAL; 469 } 470 471 rc = -ENOMEM; 472 einj_debug_dir = debugfs_create_dir("einj", apei_get_debugfs_dir()); 473 if (!einj_debug_dir) 474 goto err_cleanup; 475 fentry = debugfs_create_file("available_error_type", S_IRUSR, 476 einj_debug_dir, NULL, 477 &available_error_type_fops); 478 if (!fentry) 479 goto err_cleanup; 480 fentry = debugfs_create_file("error_type", S_IRUSR | S_IWUSR, 481 einj_debug_dir, NULL, &error_type_fops); 482 if (!fentry) 483 goto err_cleanup; 484 fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR, 485 einj_debug_dir, &error_param1); 486 if (!fentry) 487 goto err_cleanup; 488 fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR, 489 einj_debug_dir, &error_param2); 490 if (!fentry) 491 goto err_cleanup; 492 fentry = debugfs_create_file("error_inject", S_IWUSR, 493 einj_debug_dir, NULL, &error_inject_fops); 494 if (!fentry) 495 goto err_cleanup; 496 497 apei_resources_init(&einj_resources); 498 einj_exec_ctx_init(&ctx); 499 rc = apei_exec_collect_resources(&ctx, &einj_resources); 500 if (rc) 501 goto err_fini; 502 rc = apei_resources_request(&einj_resources, "APEI EINJ"); 503 if (rc) 504 goto err_fini; 505 rc = apei_exec_pre_map_gars(&ctx); 506 if (rc) 507 goto err_release; 508 param_paddr = einj_get_parameter_address(); 509 if (param_paddr) { 510 einj_param = ioremap(param_paddr, sizeof(*einj_param)); 511 rc = -ENOMEM; 512 if (!einj_param) 513 goto err_unmap; 514 } 515 516 pr_info(EINJ_PFX "Error INJection is initialized.\n"); 517 518 return 0; 519 520 err_unmap: 521 apei_exec_post_unmap_gars(&ctx); 522 err_release: 523 apei_resources_release(&einj_resources); 524 err_fini: 525 apei_resources_fini(&einj_resources); 526 err_cleanup: 527 debugfs_remove_recursive(einj_debug_dir); 528 529 return rc; 530 } 531 532 static void __exit einj_exit(void) 533 { 534 struct apei_exec_context ctx; 535 536 if (einj_param) 537 iounmap(einj_param); 538 einj_exec_ctx_init(&ctx); 539 apei_exec_post_unmap_gars(&ctx); 540 apei_resources_release(&einj_resources); 541 apei_resources_fini(&einj_resources); 542 debugfs_remove_recursive(einj_debug_dir); 543 } 544 545 module_init(einj_init); 546 module_exit(einj_exit); 547 548 MODULE_AUTHOR("Huang Ying"); 549 MODULE_DESCRIPTION("APEI Error INJection support"); 550 MODULE_LICENSE("GPL"); 551