ACPI: APEI: EINJ: Fix EINJV2 memory error injection
Subsystems (3)
Tony Luck
reviewerv4 cover ACPI: APEI: EINJ: Fix EINJV2 memory error injection
EINJV2 (introduced in version 6.5 of the ACPI specification) uses different values for the "type" of injection. Two places in the Linux driver need patching to take account of the new type values.
Changes since V3:
* Moved the #defines for EINV2 types to <acpi/actbl1.h> [Change submitted through ACPICA tree with duplicate in patch 1 of this series]
* Sashiko noted that I'd dropped the test for "flags & SETWA_FLAGS_MEM" from my is_memory_injection() helper.
Tony Luck (2):
ACPICA: Provide #defines for EINJV2 error types
ACPI: APEI: EINJ: Fix EINJV2 memory error injection
include/acpi/actbl1.h | 6 +++++ drivers/acpi/apei/einj-core.c | 45 +++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 20 deletions(-)
base-commit: 028ef9c96e96197026887c0f092424679298aae8
Signature · 1 line
2.53.0
Tony Luck
reviewerPATCH v4 1/2 ACPICA: Provide #defines for EINJV2 error types
EINJV2 defined new error types by moving the severity (correctable, uncorrectable non-fatal, uncorrectable fatal) out of the "type".
ACPI 6.5 introduced EINJV2 and defined a vendor defined error type using bit 31. This was dropped in ACPI 6.6.
---
Already applied to https://github.com/acpica/acpica.git as commit e82d2d2fd145 ("Provide #defines for EINJV2 error types")
include/acpi/actbl1.h | 6 ++++++ 1 file changed, 6 insertions(+)
include/acpi/actbl1.h +6 -0
@@ -1386,6 +1386,12 @@ enum acpi_einj_command_status {#define ACPI_EINJ_CXL_MEM_FATAL (1<<17)#define ACPI_EINJ_VENDOR_DEFINED (1<<31) +/* EINJV2 error types from EINJV2_GET_ERROR_TYPE (ACPI 6.6) */ + +#define ACPI_EINJV2_PROCESSOR (1) +#define ACPI_EINJV2_MEMORY (1<<1) +#define ACPI_EINJV2_PCIE (1<<2) +/******************************************************************************* * * ERST - Error Record Serialization Table (ACPI 4.0)
Signature · 1 line
2.53.0
Rafael J. Wysocki
maintainerRe: [PATCH v4 1/2] ACPICA: Provide #defines for EINJV2 error types
Quoted 4 lines · Tony Luck
EINJV2 defined new error types by moving the severity (correctable, uncorrectable non-fatal, uncorrectable fatal) out of the "type".
Quoted 8 lines
ACPI 6.5 introduced EINJV2 and defined a vendor defined error type using bit 31. This was dropped in ACPI 6.6.
Signed-off-by Tony Luck <[email protected]>---
Already applied to https://github.com/acpica/acpica.git as commite82d2d2fd145("Provide #defines for EINJV2 error types")
So you do
which I've done already for this one and applied it as 7.1-rc material along with the [2/2].
Thanks!
Quoted 26 lines
include/acpi/actbl1.h | 6 ++++++ 1 file changed, 6 insertions(+)include/acpi/actbl1.h +6
-1@@ -1386,6 +1386,12 @@ enum acpi_einj_command_status {#define ACPI_EINJ_CXL_MEM_FATAL (1<<17)#define ACPI_EINJ_VENDOR_DEFINED (1<<31) +/* EINJV2 error types from EINJV2_GET_ERROR_TYPE (ACPI 6.6) */ + +#define ACPI_EINJV2_PROCESSOR (1) +#define ACPI_EINJV2_MEMORY (1<<1) +#define ACPI_EINJV2_PCIE (1<<2) +/******************************************************************************* * * ERST - Error Record Serialization Table (ACPI 4.0) -- 2.53.0
Tony Luck
reviewerPATCH v4 2/2 ACPI: APEI: EINJ: Fix EINJV2 memory error injection
In reply to Tony LuckError types in EINJV2 use different bit positions for each flavor of injection from legacy EINJ.
Two issues:
1) The address sanity checks in einj_error_inject() were skipped for EINJV2 injections. Noted by sashiko[1]
2) __einj_error_trigger() failed to drop the entry of the target physical address from the list of resources that need to be requested.
Add a helper function that checks if an injection is to memory and use it to solve each of these issues.
Note that the old test in __einj_error_trigger() checked that param2 was not zero. This isn't needed because the sanity checks in einj_error_inject() reject memory injections with param2 == 0.
#Reported-by: sashiko <[email protected]>
--- drivers/acpi/apei/einj-core.c | 45 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 20 deletions(-)
drivers/acpi/apei/einj-core.c +25 -20
@@ -401,8 +401,18 @@ static struct acpi_generic_address *einj_get_trigger_parameter_region(return NULL ; } + +static bool is_memory_injection (u32 type,u32 flags) +{ +if (flags &SETWA_FLAGS_EINJV2 ) +return !!(type &ACPI_EINJV2_MEMORY ); +if (type &ACPI5_VENDOR_BIT ) +return !!(vendor_flags &SETWA_FLAGS_MEM ); +return !!(type &MEM_ERROR_MASK ) || !!(flags &SETWA_FLAGS_MEM ); +} +/* Execute instructions in trigger error action table */ -static int __einj_error_trigger (u64 trigger_paddr,u32 type, +static int __einj_error_trigger (u64 trigger_paddr,u32 type,u32 flags,u64 param1,u64 param2) {struct acpi_einj_trigger trigger_tab;
@@ -480,7 +490,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 &MEM_ERROR_MASK ) && param2) { +if ((param_extension || acpi5) &&is_memory_injection (type, flags)) {struct apei_resources addr_resources;apei_resources_init (&addr_resources);
@@ -660,7 +670,7 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,return rc; trigger_paddr =apei_exec_ctx_get_output (&ctx);if (notrigger ==0 ) { - rc =__einj_error_trigger (trigger_paddr, type, param1, param2); + rc =__einj_error_trigger (trigger_paddr, type, flags, param1, param2);if (rc)return rc; }
@@ -718,35 +728,30 @@ int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3, SETWA_FLAGS_PCIE_SBDF | SETWA_FLAGS_EINJV2)))return -EINVAL ; +/* +* Injections targeting a CXL 1.0/1.1 port have to be injected +* via the einj_cxl_rch_error_inject() path as that does the proper +* validation of the given RCRB base (MMIO) address. +*/ +if (einj_is_cxl_error_type (type) && (flags &SETWA_FLAGS_MEM )) +return -EINVAL ; +/* check if type is a valid EINJv2 error type */ if (is_v2) {if (!(type & available_error_type_v2))return -EINVAL ; } -/* -* 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 ) && !(flags &SETWA_FLAGS_MEM )) { - goto inject; - } -/* -* Injections targeting a CXL 1.0/1.1 port have to be injected -* via the einj_cxl_rch_error_inject() path as that does the proper -* validation of the given RCRB base (MMIO) address. +* We need extra sanity checks for memory errors. +* Other types leap directly to injection. */ -if (einj_is_cxl_error_type (type) && (flags &SETWA_FLAGS_MEM )) -return -EINVAL ; +if (!is_memory_injection (type, flags)) + goto inject;/* * Disallow crazy address masks that give BIOS leeway to pick
Signature · 1 line
2.53.0
Quoted 120 lines · Tony Luck
Error types in EINJV2 use different bit positions for each flavor of injection from legacy EINJ.
Two issues:
1) The address sanity checks in
einj_error_inject()were skipped for EINJV2 injections. Noted by sashiko[1]
2)__einj_error_trigger()failed to drop the entry of the target physical address from the list of resources that need to be requested.Add a helper function that checks if an injection is to memory and use it to solve each of these issues.
Note that the old test in
__einj_error_trigger()checked that param2 was not zero. This isn't needed because the sanity checks ineinj_error_inject()reject memory injections with param2 == 0.Fixes b47610296d17 ("ACPI: APEI: EINJ: Enable EINJv2 error injections")#Reported-by: sashiko <[email protected]>
Reported-by Herman Li <[email protected]>Signed-off-by Tony Luck <[email protected]>Tested-by "Lai, Yi1" <[email protected]>--- drivers/acpi/apei/einj-core.c | 45 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 20 deletions(-)drivers/acpi/apei/einj-core.c +25
-21@@ -401,8 +401,18 @@ static struct acpi_generic_address *einj_get_trigger_parameter_region(return NULL ; } + +static bool is_memory_injection (u32 type,u32 flags) +{ +if (flags &SETWA_FLAGS_EINJV2 ) +return !!(type &ACPI_EINJV2_MEMORY ); +if (type &ACPI5_VENDOR_BIT ) +return !!(vendor_flags &SETWA_FLAGS_MEM ); +return !!(type &MEM_ERROR_MASK ) || !!(flags &SETWA_FLAGS_MEM ); +} +/* Execute instructions in trigger error action table */ -static int __einj_error_trigger (u64 trigger_paddr,u32 type, +static int __einj_error_trigger (u64 trigger_paddr,u32 type,u32 flags,u64 param1,u64 param2) {struct acpi_einj_trigger trigger_tab;@@ -480,7 +490,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 &MEM_ERROR_MASK ) && param2) { +if ((param_extension || acpi5) &&is_memory_injection (type, flags)) {struct apei_resources addr_resources;apei_resources_init (&addr_resources);@@ -660,7 +670,7 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,return rc; trigger_paddr =apei_exec_ctx_get_output (&ctx);if (notrigger ==0 ) { - rc =__einj_error_trigger (trigger_paddr, type, param1, param2); + rc =__einj_error_trigger (trigger_paddr, type, flags, param1, param2);if (rc)return rc; }@@ -718,35 +728,30 @@ int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3, SETWA_FLAGS_PCIE_SBDF | SETWA_FLAGS_EINJV2)))return -EINVAL ; +/* +* Injections targeting a CXL 1.0/1.1 port have to be injected +* via the einj_cxl_rch_error_inject() path as that does the proper +* validation of the given RCRB base (MMIO) address. +*/ +if (einj_is_cxl_error_type (type) && (flags &SETWA_FLAGS_MEM )) +return -EINVAL ; +/* check if type is a valid EINJv2 error type */ if (is_v2) {if (!(type & available_error_type_v2))return -EINVAL ; } -/* -* 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 ) && !(flags &SETWA_FLAGS_MEM )) { - goto inject; - } -/* -* Injections targeting a CXL 1.0/1.1 port have to be injected -* via the einj_cxl_rch_error_inject() path as that does the proper -* validation of the given RCRB base (MMIO) address. +* We need extra sanity checks for memory errors. +* Other types leap directly to injection. */ -if (einj_is_cxl_error_type (type) && (flags &SETWA_FLAGS_MEM )) -return -EINVAL ; +if (!is_memory_injection (type, flags)) + goto inject;/* * Disallow crazy address masks that give BIOS leeway to pick --
Quoted 2 lines
2.53.0
Quoted 121 lines · Tony Luck
Error types in EINJV2 use different bit positions for each flavor of injection from legacy EINJ.
Two issues:
1) The address sanity checks in
einj_error_inject()were skipped for EINJV2 injections. Noted by sashiko[1]
2)__einj_error_trigger()failed to drop the entry of the target physical address from the list of resources that need to be requested.Add a helper function that checks if an injection is to memory and use it to solve each of these issues.
Note that the old test in
__einj_error_trigger()checked that param2 was not zero. This isn't needed because the sanity checks ineinj_error_inject()reject memory injections with param2 == 0.Fixes b47610296d17 ("ACPI: APEI: EINJ: Enable EINJv2 error injections")#Reported-by: sashiko <[email protected]>
Reported-by Herman Li <[email protected]>Signed-off-by Tony Luck <[email protected]>Tested-by "Lai, Yi1" <[email protected]>--- drivers/acpi/apei/einj-core.c | 45 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 20 deletions(-)drivers/acpi/apei/einj-core.c +25
-20@@ -401,8 +401,18 @@ static struct acpi_generic_address *einj_get_trigger_parameter_region(return NULL ; } + +static bool is_memory_injection (u32 type,u32 flags) +{ +if (flags &SETWA_FLAGS_EINJV2 ) +return !!(type &ACPI_EINJV2_MEMORY ); +if (type &ACPI5_VENDOR_BIT ) +return !!(vendor_flags &SETWA_FLAGS_MEM ); +return !!(type &MEM_ERROR_MASK ) || !!(flags &SETWA_FLAGS_MEM ); +} +/* Execute instructions in trigger error action table */ -static int __einj_error_trigger (u64 trigger_paddr,u32 type, +static int __einj_error_trigger (u64 trigger_paddr,u32 type,u32 flags,u64 param1,u64 param2) {struct acpi_einj_trigger trigger_tab;@@ -480,7 +490,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 &MEM_ERROR_MASK ) && param2) { +if ((param_extension || acpi5) &&is_memory_injection (type, flags)) {struct apei_resources addr_resources;apei_resources_init (&addr_resources);@@ -660,7 +670,7 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,return rc; trigger_paddr =apei_exec_ctx_get_output (&ctx);if (notrigger ==0 ) { - rc =__einj_error_trigger (trigger_paddr, type, param1, param2); + rc =__einj_error_trigger (trigger_paddr, type, flags, param1, param2);if (rc)return rc; }@@ -718,35 +728,30 @@ int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3, SETWA_FLAGS_PCIE_SBDF | SETWA_FLAGS_EINJV2)))return -EINVAL ; +/* +* Injections targeting a CXL 1.0/1.1 port have to be injected +* via the einj_cxl_rch_error_inject() path as that does the proper +* validation of the given RCRB base (MMIO) address. +*/ +if (einj_is_cxl_error_type (type) && (flags &SETWA_FLAGS_MEM )) +return -EINVAL ; +/* check if type is a valid EINJv2 error type */ if (is_v2) {if (!(type & available_error_type_v2))return -EINVAL ; } -/* -* 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 ) && !(flags &SETWA_FLAGS_MEM )) { - goto inject; - } -/* -* Injections targeting a CXL 1.0/1.1 port have to be injected -* via the einj_cxl_rch_error_inject() path as that does the proper -* validation of the given RCRB base (MMIO) address. +* We need extra sanity checks for memory errors. +* Other types leap directly to injection. */ -if (einj_is_cxl_error_type (type) && (flags &SETWA_FLAGS_MEM )) -return -EINVAL ; +if (!is_memory_injection (type, flags)) + goto inject;/* * Disallow crazy address masks that give BIOS leeway to pick Signature · 1 line
2.53.0