| From 7ba75db79ce55a075f0741ff01b605a7ad49b258 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 14 Jan 2026 13:25:33 +0100 |
| Subject: ACPICA: Abort AML bytecode execution when executing AML_FATAL_OP |
| |
| From: Armin Wolf <W_Armin@gmx.de> |
| |
| [ Upstream commit 026ad376a6a48538b576f3589331daa94daae6f0 ] |
| |
| The ACPI specification states that when executing AML_FATAL_OP, |
| the OS should log the fatal error event and shutdown in a timely |
| fashion. |
| |
| Windows complies with this requirement by immediatly entering a |
| Bso_d, effectively aborting the execution of the AML bytecode in |
| question. |
| |
| ACPICA however might continue with the AML bytecode execution |
| should acpi_os_signal() simply return AE_OK. This will cause issues |
| because ACPI BIOS implementations might assume that the Fatal() |
| operator does not return. |
| |
| Fix this by aborting the AML bytecode execution in such a case |
| by returning AE_ERROR. Also turn struct acpi_signal_fatal_info into a |
| local variable because of its small size (12 bytes) and to ensure |
| that acpi_os_signal() always receives valid information about the |
| fatal ACPI BIOS error. |
| |
| Link: https://github.com/acpica/acpica/commit/d516c7758ba6 |
| Signed-off-by: Armin Wolf <W_Armin@gmx.de> |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Link: https://patch.msgid.link/3325491.5fSG56mABF@rafael.j.wysocki |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/acpi/acpica/exoparg3.c | 46 +++++++++++++--------------------- |
| 1 file changed, 18 insertions(+), 28 deletions(-) |
| |
| diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c |
| index c8d0d75fc4505..962929d4abbfc 100644 |
| --- a/drivers/acpi/acpica/exoparg3.c |
| +++ b/drivers/acpi/acpica/exoparg3.c |
| @@ -10,6 +10,7 @@ |
| #include <acpi/acpi.h> |
| #include "accommon.h" |
| #include "acinterp.h" |
| +#include <acpi/acoutput.h> |
| #include "acparser.h" |
| #include "amlcode.h" |
| |
| @@ -51,8 +52,7 @@ ACPI_MODULE_NAME("exoparg3") |
| acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) |
| { |
| union acpi_operand_object **operand = &walk_state->operands[0]; |
| - struct acpi_signal_fatal_info *fatal; |
| - acpi_status status = AE_OK; |
| + struct acpi_signal_fatal_info fatal; |
| |
| ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R, |
| acpi_ps_get_opcode_name(walk_state->opcode)); |
| @@ -60,28 +60,23 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) |
| switch (walk_state->opcode) { |
| case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ |
| |
| - ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| - "FatalOp: Type %X Code %X Arg %X " |
| - "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", |
| - (u32)operand[0]->integer.value, |
| - (u32)operand[1]->integer.value, |
| - (u32)operand[2]->integer.value)); |
| - |
| - fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); |
| - if (fatal) { |
| - fatal->type = (u32) operand[0]->integer.value; |
| - fatal->code = (u32) operand[1]->integer.value; |
| - fatal->argument = (u32) operand[2]->integer.value; |
| - } |
| + fatal.type = (u32)operand[0]->integer.value; |
| + fatal.code = (u32)operand[1]->integer.value; |
| + fatal.argument = (u32)operand[2]->integer.value; |
| |
| - /* Always signal the OS! */ |
| + ACPI_BIOS_ERROR((AE_INFO, |
| + "Fatal ACPI BIOS error (Type 0x%X Code 0x%X Arg 0x%X)\n", |
| + fatal.type, fatal.code, fatal.argument)); |
| |
| - status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal); |
| + /* Always signal the OS! */ |
| |
| - /* Might return while OS is shutting down, just continue */ |
| + acpi_os_signal(ACPI_SIGNAL_FATAL, &fatal); |
| |
| - ACPI_FREE(fatal); |
| - goto cleanup; |
| + /* |
| + * Might return while OS is shutting down, so abort the AML execution |
| + * by returning an error. |
| + */ |
| + return_ACPI_STATUS(AE_ERROR); |
| |
| case AML_EXTERNAL_OP: |
| /* |
| @@ -93,21 +88,16 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) |
| * wrong if an external opcode ever gets here. |
| */ |
| ACPI_ERROR((AE_INFO, "Executed External Op")); |
| - status = AE_OK; |
| - goto cleanup; |
| + |
| + return_ACPI_STATUS(AE_OK); |
| |
| default: |
| |
| ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", |
| walk_state->opcode)); |
| |
| - status = AE_AML_BAD_OPCODE; |
| - goto cleanup; |
| + return_ACPI_STATUS(AE_AML_BAD_OPCODE); |
| } |
| - |
| -cleanup: |
| - |
| - return_ACPI_STATUS(status); |
| } |
| |
| /******************************************************************************* |
| -- |
| 2.51.0 |
| |