Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'please-pull-einj' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras into x86/ras

Pull error injection update from Tony Luck:

* Add more flexibility to the error injection (EINJ) debugfs interface

Signed-off-by: Ingo Molnar <mingo@kernel.org>

+52 -6
+18 -1
Documentation/acpi/apei/einj.txt
··· 45 45 injection. Before this, please specify all necessary error 46 46 parameters. 47 47 48 + - flags 49 + Present for kernel version 3.13 and above. Used to specify which 50 + of param{1..4} are valid and should be used by BIOS during injection. 51 + Value is a bitmask as specified in ACPI5.0 spec for the 52 + SET_ERROR_TYPE_WITH_ADDRESS data structure: 53 + Bit 0 - Processor APIC field valid (see param3 below) 54 + Bit 1 - Memory address and mask valid (param1 and param2) 55 + Bit 2 - PCIe (seg,bus,dev,fn) valid (param4 below) 56 + If set to zero, legacy behaviour is used where the type of injection 57 + specifies just one bit set, and param1 is multiplexed. 58 + 48 59 - param1 49 60 This file is used to set the first error parameter value. Effect of 50 61 parameter depends on error_type specified. For example, if error 51 62 type is memory related type, the param1 should be a valid physical 52 - memory address. 63 + memory address. [Unless "flag" is set - see above] 53 64 54 65 - param2 55 66 This file is used to set the second error parameter value. Effect of ··· 68 57 type is memory related type, the param2 should be a physical memory 69 58 address mask. Linux requires page or narrower granularity, say, 70 59 0xfffffffffffff000. 60 + 61 + - param3 62 + Used when the 0x1 bit is set in "flag" to specify the APIC id 63 + 64 + - param4 65 + Used when the 0x4 bit is set in "flag" to specify target PCIe device 71 66 72 67 - notrigger 73 68 The EINJ mechanism is a two step process. First inject the error, then
+34 -5
drivers/acpi/apei/einj.c
··· 416 416 return rc; 417 417 } 418 418 419 - static int __einj_error_inject(u32 type, u64 param1, u64 param2) 419 + static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, 420 + u64 param3, u64 param4) 420 421 { 421 422 struct apei_exec_context ctx; 422 423 u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT; ··· 447 446 break; 448 447 } 449 448 v5param->flags = vendor_flags; 449 + } else if (flags) { 450 + v5param->flags = flags; 451 + v5param->memory_address = param1; 452 + v5param->memory_address_range = param2; 453 + v5param->apicid = param3; 454 + v5param->pcie_sbdf = param4; 450 455 } else { 451 456 switch (type) { 452 457 case ACPI_EINJ_PROCESSOR_CORRECTABLE: ··· 521 514 } 522 515 523 516 /* Inject the specified hardware error */ 524 - static int einj_error_inject(u32 type, u64 param1, u64 param2) 517 + static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, 518 + u64 param3, u64 param4) 525 519 { 526 520 int rc; 527 521 unsigned long pfn; 522 + 523 + /* If user manually set "flags", make sure it is legal */ 524 + if (flags && (flags & 525 + ~(SETWA_FLAGS_APICID|SETWA_FLAGS_MEM|SETWA_FLAGS_PCIE_SBDF))) 526 + return -EINVAL; 528 527 529 528 /* 530 529 * We need extra sanity checks for memory errors. ··· 545 532 if (type & ACPI5_VENDOR_BIT) { 546 533 if (vendor_flags != SETWA_FLAGS_MEM) 547 534 goto inject; 548 - } else if (!(type & MEM_ERROR_MASK)) 535 + } else if (!(type & MEM_ERROR_MASK) && !(flags & SETWA_FLAGS_MEM)) 549 536 goto inject; 550 537 551 538 /* ··· 559 546 560 547 inject: 561 548 mutex_lock(&einj_mutex); 562 - rc = __einj_error_inject(type, param1, param2); 549 + rc = __einj_error_inject(type, flags, param1, param2, param3, param4); 563 550 mutex_unlock(&einj_mutex); 564 551 565 552 return rc; 566 553 } 567 554 568 555 static u32 error_type; 556 + static u32 error_flags; 569 557 static u64 error_param1; 570 558 static u64 error_param2; 559 + static u64 error_param3; 560 + static u64 error_param4; 571 561 static struct dentry *einj_debug_dir; 572 562 573 563 static int available_error_type_show(struct seq_file *m, void *v) ··· 664 648 if (!error_type) 665 649 return -EINVAL; 666 650 667 - return einj_error_inject(error_type, error_param1, error_param2); 651 + return einj_error_inject(error_type, error_flags, error_param1, error_param2, 652 + error_param3, error_param4); 668 653 } 669 654 670 655 DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, ··· 746 729 rc = -ENOMEM; 747 730 einj_param = einj_get_parameter_address(); 748 731 if ((param_extension || acpi5) && einj_param) { 732 + fentry = debugfs_create_x32("flags", S_IRUSR | S_IWUSR, 733 + einj_debug_dir, &error_flags); 734 + if (!fentry) 735 + goto err_unmap; 749 736 fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR, 750 737 einj_debug_dir, &error_param1); 751 738 if (!fentry) 752 739 goto err_unmap; 753 740 fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR, 754 741 einj_debug_dir, &error_param2); 742 + if (!fentry) 743 + goto err_unmap; 744 + fentry = debugfs_create_x64("param3", S_IRUSR | S_IWUSR, 745 + einj_debug_dir, &error_param3); 746 + if (!fentry) 747 + goto err_unmap; 748 + fentry = debugfs_create_x64("param4", S_IRUSR | S_IWUSR, 749 + einj_debug_dir, &error_param4); 755 750 if (!fentry) 756 751 goto err_unmap; 757 752