ACPICA: Add a mechanism to escape infinite AML While() loops
Add a loop counter to force exit from AML While loops if the count becomes too large. This can occur in poorly written AML when the hardware does not respond within a while loop and the loop does not implement a timeout. The maximum loop count is configurable. A new exception code is returned when a loop is broken, AE_AML_INFINITE_LOOP. Bob Moore, Alexey Starikovskiy. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
Родитель
96411a6304
Коммит
fc37445733
|
@ -1262,13 +1262,31 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
|
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
|
||||||
|
|
||||||
if (walk_state->control_state->common.value) {
|
control_state = walk_state->control_state;
|
||||||
|
if (control_state->common.value) {
|
||||||
|
|
||||||
/* Predicate was true, go back and evaluate it again! */
|
/* Predicate was true, the body of the loop was just executed */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This loop counter mechanism allows the interpreter to escape
|
||||||
|
* possibly infinite loops. This can occur in poorly written AML
|
||||||
|
* when the hardware does not respond within a while loop and the
|
||||||
|
* loop does not implement a timeout.
|
||||||
|
*/
|
||||||
|
control_state->control.loop_count++;
|
||||||
|
if (control_state->control.loop_count >
|
||||||
|
ACPI_MAX_LOOP_ITERATIONS) {
|
||||||
|
status = AE_AML_INFINITE_LOOP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go back and evaluate the predicate and maybe execute the loop
|
||||||
|
* another time
|
||||||
|
*/
|
||||||
status = AE_CTRL_PENDING;
|
status = AE_CTRL_PENDING;
|
||||||
walk_state->aml_last_while =
|
walk_state->aml_last_while =
|
||||||
walk_state->control_state->control.aml_predicate_start;
|
control_state->control.aml_predicate_start;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,10 @@
|
||||||
|
|
||||||
#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4
|
#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4
|
||||||
|
|
||||||
|
/* Maximum number of While() loop iterations before forced abort */
|
||||||
|
|
||||||
|
#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* ACPI Specification constants (Do not change unless the specification changes)
|
* ACPI Specification constants (Do not change unless the specification changes)
|
||||||
|
|
|
@ -153,8 +153,9 @@
|
||||||
#define AE_AML_CIRCULAR_REFERENCE (acpi_status) (0x001E | AE_CODE_AML)
|
#define AE_AML_CIRCULAR_REFERENCE (acpi_status) (0x001E | AE_CODE_AML)
|
||||||
#define AE_AML_BAD_RESOURCE_LENGTH (acpi_status) (0x001F | AE_CODE_AML)
|
#define AE_AML_BAD_RESOURCE_LENGTH (acpi_status) (0x001F | AE_CODE_AML)
|
||||||
#define AE_AML_ILLEGAL_ADDRESS (acpi_status) (0x0020 | AE_CODE_AML)
|
#define AE_AML_ILLEGAL_ADDRESS (acpi_status) (0x0020 | AE_CODE_AML)
|
||||||
|
#define AE_AML_INFINITE_LOOP (acpi_status) (0x0021 | AE_CODE_AML)
|
||||||
|
|
||||||
#define AE_CODE_AML_MAX 0x0020
|
#define AE_CODE_AML_MAX 0x0021
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal exceptions used for control
|
* Internal exceptions used for control
|
||||||
|
@ -267,6 +268,7 @@ char const *acpi_gbl_exception_names_aml[] = {
|
||||||
"AE_AML_CIRCULAR_REFERENCE",
|
"AE_AML_CIRCULAR_REFERENCE",
|
||||||
"AE_AML_BAD_RESOURCE_LENGTH",
|
"AE_AML_BAD_RESOURCE_LENGTH",
|
||||||
"AE_AML_ILLEGAL_ADDRESS",
|
"AE_AML_ILLEGAL_ADDRESS",
|
||||||
|
"AE_AML_INFINITE_LOOP"
|
||||||
};
|
};
|
||||||
|
|
||||||
char const *acpi_gbl_exception_names_ctrl[] = {
|
char const *acpi_gbl_exception_names_ctrl[] = {
|
||||||
|
|
|
@ -566,6 +566,7 @@ struct acpi_control_state {
|
||||||
union acpi_parse_object *predicate_op;
|
union acpi_parse_object *predicate_op;
|
||||||
u8 *aml_predicate_start; /* Start of if/while predicate */
|
u8 *aml_predicate_start; /* Start of if/while predicate */
|
||||||
u8 *package_end; /* End of if/while block */
|
u8 *package_end; /* End of if/while block */
|
||||||
|
u32 loop_count; /* While() loop counter */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче