mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 00:51:51 -04:00
ACPI: APEI: EINJ: Fix EINJV2 memory error injection
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 in einj_error_inject()
reject memory injections with param2 == 0.
Fixes: b47610296d ("ACPI: APEI: EINJ: Enable EINJv2 error injections")
Reported-by: sashiko <sashiko@sashiko.dev>
Reported-by: Herman Li <herman.li@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Tested-by: "Lai, Yi1" <yi1.lai@intel.com>
Link: https://sashiko.dev/#/patchset/20260415163620.12957-1-tony.luck%40intel.com # [1]
Reviewed-by: Jiaqi Yan <jiaqiyan@google.com>
Reviewed-by: Zaid Alali <zaidal@os.amperecomputing.com>
Link: https://patch.msgid.link/20260421150216.11666-3-tony.luck@intel.com
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
committed by
Rafael J. Wysocki
parent
1f60085383
commit
0c00cfbcfc
@@ -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,28 +728,6 @@ int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3,
|
||||
SETWA_FLAGS_PCIE_SBDF | SETWA_FLAGS_EINJV2)))
|
||||
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
|
||||
@@ -748,6 +736,23 @@ int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3,
|
||||
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;
|
||||
}
|
||||
|
||||
/* ensure param1/param2 existed */
|
||||
if (!(param_extension || acpi5))
|
||||
goto inject;
|
||||
|
||||
/*
|
||||
* We need extra sanity checks for memory errors.
|
||||
* Other types leap directly to injection.
|
||||
*/
|
||||
if (!is_memory_injection(type, flags))
|
||||
goto inject;
|
||||
|
||||
/*
|
||||
* Disallow crazy address masks that give BIOS leeway to pick
|
||||
* injection address almost anywhere. Insist on page or
|
||||
|
||||
Reference in New Issue
Block a user