Loading Documentation/acpi/apei/einj.txt +7 −2 Original line number Diff line number Diff line Loading @@ -47,11 +47,16 @@ directory apei/einj. The following files are provided. - param1 This file is used to set the first error parameter value. Effect of parameter depends on error_type specified. parameter depends on error_type specified. For example, if error type is memory related type, the param1 should be a valid physical memory address. - param2 This file is used to set the second error parameter value. Effect of parameter depends on error_type specified. parameter depends on error_type specified. For example, if error type is memory related type, the param2 should be a physical memory address mask. Linux requires page or narrower granularity, say, 0xfffffffffffff000. - notrigger The EINJ mechanism is a two step process. First inject the error, then Loading drivers/acpi/apei/einj.c +36 −3 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <linux/seq_file.h> #include <linux/nmi.h> #include <linux/delay.h> #include <linux/mm.h> #include <acpi/acpi.h> #include "apei-internal.h" Loading @@ -41,6 +42,10 @@ #define SPIN_UNIT 100 /* 100ns */ /* Firmware should respond within 1 milliseconds */ #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) #define ACPI5_VENDOR_BIT BIT(31) #define MEM_ERROR_MASK (ACPI_EINJ_MEMORY_CORRECTABLE | \ ACPI_EINJ_MEMORY_UNCORRECTABLE | \ ACPI_EINJ_MEMORY_FATAL) /* * ACPI version 5 provides a SET_ERROR_TYPE_WITH_ADDRESS action. Loading Loading @@ -367,7 +372,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, * This will cause resource conflict with regular memory. So * remove it from trigger table resources. */ if ((param_extension || acpi5) && (type & 0x0038) && param2) { if ((param_extension || acpi5) && (type & MEM_ERROR_MASK) && param2) { struct apei_resources addr_resources; apei_resources_init(&addr_resources); trigger_param_region = einj_get_trigger_parameter_region( Loading Loading @@ -427,7 +432,7 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) struct set_error_type_with_address *v5param = einj_param; v5param->type = type; if (type & 0x80000000) { if (type & ACPI5_VENDOR_BIT) { switch (vendor_flags) { case SETWA_FLAGS_APICID: v5param->apicid = param1; Loading Loading @@ -512,7 +517,34 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) static int einj_error_inject(u32 type, u64 param1, u64 param2) { int rc; unsigned long pfn; /* * We need extra sanity checks for memory errors. * Other types leap directly to injection. */ /* ensure param1/param2 existed */ if (!(param_extension || acpi5)) goto inject; /* ensure injection is memory related */ if (type & ACPI5_VENDOR_BIT) { if (vendor_flags != SETWA_FLAGS_MEM) goto inject; } else if (!(type & MEM_ERROR_MASK)) goto inject; /* * Disallow crazy address masks that give BIOS leeway to pick * injection address almost anywhere. Insist on page or * better granularity and that target address is normal RAM. */ pfn = PFN_DOWN(param1 & param2); if (!page_is_ram(pfn) || ((param2 & PAGE_MASK) != PAGE_MASK)) return -EINVAL; inject: mutex_lock(&einj_mutex); rc = __einj_error_inject(type, param1, param2); mutex_unlock(&einj_mutex); Loading Loading @@ -590,7 +622,7 @@ static int error_type_set(void *data, u64 val) * Vendor defined types have 0x80000000 bit set, and * are not enumerated by ACPI_EINJ_GET_ERROR_TYPE */ vendor = val & 0x80000000; vendor = val & ACPI5_VENDOR_BIT; tval = val & 0x7fffffff; /* Only one error type can be specified */ Loading Loading @@ -694,6 +726,7 @@ static int __init einj_init(void) if (rc) goto err_release; rc = -ENOMEM; einj_param = einj_get_parameter_address(); if ((param_extension || acpi5) && einj_param) { fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR, Loading kernel/resource.c +1 −0 Original line number Diff line number Diff line Loading @@ -409,6 +409,7 @@ int __weak page_is_ram(unsigned long pfn) { return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1; } EXPORT_SYMBOL_GPL(page_is_ram); void __weak arch_remove_reservations(struct resource *avail) { Loading Loading
Documentation/acpi/apei/einj.txt +7 −2 Original line number Diff line number Diff line Loading @@ -47,11 +47,16 @@ directory apei/einj. The following files are provided. - param1 This file is used to set the first error parameter value. Effect of parameter depends on error_type specified. parameter depends on error_type specified. For example, if error type is memory related type, the param1 should be a valid physical memory address. - param2 This file is used to set the second error parameter value. Effect of parameter depends on error_type specified. parameter depends on error_type specified. For example, if error type is memory related type, the param2 should be a physical memory address mask. Linux requires page or narrower granularity, say, 0xfffffffffffff000. - notrigger The EINJ mechanism is a two step process. First inject the error, then Loading
drivers/acpi/apei/einj.c +36 −3 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <linux/seq_file.h> #include <linux/nmi.h> #include <linux/delay.h> #include <linux/mm.h> #include <acpi/acpi.h> #include "apei-internal.h" Loading @@ -41,6 +42,10 @@ #define SPIN_UNIT 100 /* 100ns */ /* Firmware should respond within 1 milliseconds */ #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) #define ACPI5_VENDOR_BIT BIT(31) #define MEM_ERROR_MASK (ACPI_EINJ_MEMORY_CORRECTABLE | \ ACPI_EINJ_MEMORY_UNCORRECTABLE | \ ACPI_EINJ_MEMORY_FATAL) /* * ACPI version 5 provides a SET_ERROR_TYPE_WITH_ADDRESS action. Loading Loading @@ -367,7 +372,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, * This will cause resource conflict with regular memory. So * remove it from trigger table resources. */ if ((param_extension || acpi5) && (type & 0x0038) && param2) { if ((param_extension || acpi5) && (type & MEM_ERROR_MASK) && param2) { struct apei_resources addr_resources; apei_resources_init(&addr_resources); trigger_param_region = einj_get_trigger_parameter_region( Loading Loading @@ -427,7 +432,7 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) struct set_error_type_with_address *v5param = einj_param; v5param->type = type; if (type & 0x80000000) { if (type & ACPI5_VENDOR_BIT) { switch (vendor_flags) { case SETWA_FLAGS_APICID: v5param->apicid = param1; Loading Loading @@ -512,7 +517,34 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) static int einj_error_inject(u32 type, u64 param1, u64 param2) { int rc; unsigned long pfn; /* * We need extra sanity checks for memory errors. * Other types leap directly to injection. */ /* ensure param1/param2 existed */ if (!(param_extension || acpi5)) goto inject; /* ensure injection is memory related */ if (type & ACPI5_VENDOR_BIT) { if (vendor_flags != SETWA_FLAGS_MEM) goto inject; } else if (!(type & MEM_ERROR_MASK)) goto inject; /* * Disallow crazy address masks that give BIOS leeway to pick * injection address almost anywhere. Insist on page or * better granularity and that target address is normal RAM. */ pfn = PFN_DOWN(param1 & param2); if (!page_is_ram(pfn) || ((param2 & PAGE_MASK) != PAGE_MASK)) return -EINVAL; inject: mutex_lock(&einj_mutex); rc = __einj_error_inject(type, param1, param2); mutex_unlock(&einj_mutex); Loading Loading @@ -590,7 +622,7 @@ static int error_type_set(void *data, u64 val) * Vendor defined types have 0x80000000 bit set, and * are not enumerated by ACPI_EINJ_GET_ERROR_TYPE */ vendor = val & 0x80000000; vendor = val & ACPI5_VENDOR_BIT; tval = val & 0x7fffffff; /* Only one error type can be specified */ Loading Loading @@ -694,6 +726,7 @@ static int __init einj_init(void) if (rc) goto err_release; rc = -ENOMEM; einj_param = einj_get_parameter_address(); if ((param_extension || acpi5) && einj_param) { fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR, Loading
kernel/resource.c +1 −0 Original line number Diff line number Diff line Loading @@ -409,6 +409,7 @@ int __weak page_is_ram(unsigned long pfn) { return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1; } EXPORT_SYMBOL_GPL(page_is_ram); void __weak arch_remove_reservations(struct resource *avail) { Loading