aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2008-11-12 02:15:29 -0500
committerLen Brown <len.brown@intel.com>2008-12-29 22:38:36 -0500
commitfc37445733aeae4fd1a20385850620354263b1d5 (patch)
treea989d6bf8dcc2011f25e365532c3855a48f11c62
parent96411a630412f057d365aa1e9de7d23c069d627a (diff)
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>
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c24
-rw-r--r--include/acpi/acconfig.h4
-rw-r--r--include/acpi/acexcep.h4
-rw-r--r--include/acpi/aclocal.h1
4 files changed, 29 insertions, 4 deletions
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 5cd406676c2c..50c892a49fa3 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -1262,13 +1262,31 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
1262 1262
1263 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); 1263 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
1264 1264
1265 if (walk_state->control_state->common.value) { 1265 control_state = walk_state->control_state;
1266 if (control_state->common.value) {
1266 1267
1267 /* Predicate was true, go back and evaluate it again! */ 1268 /* Predicate was true, the body of the loop was just executed */
1268 1269
1270 /*
1271 * This loop counter mechanism allows the interpreter to escape
1272 * possibly infinite loops. This can occur in poorly written AML
1273 * when the hardware does not respond within a while loop and the
1274 * loop does not implement a timeout.
1275 */
1276 control_state->control.loop_count++;
1277 if (control_state->control.loop_count >
1278 ACPI_MAX_LOOP_ITERATIONS) {
1279 status = AE_AML_INFINITE_LOOP;
1280 break;
1281 }
1282
1283 /*
1284 * Go back and evaluate the predicate and maybe execute the loop
1285 * another time
1286 */
1269 status = AE_CTRL_PENDING; 1287 status = AE_CTRL_PENDING;
1270 walk_state->aml_last_while = 1288 walk_state->aml_last_while =
1271 walk_state->control_state->control.aml_predicate_start; 1289 control_state->control.aml_predicate_start;
1272 break; 1290 break;
1273 } 1291 }
1274 1292
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 29feee27f0ea..e50fe7157463 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -119,6 +119,10 @@
119 119
120#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4 120#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4
121 121
122/* Maximum number of While() loop iterations before forced abort */
123
124#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF
125
122/****************************************************************************** 126/******************************************************************************
123 * 127 *
124 * ACPI Specification constants (Do not change unless the specification changes) 128 * ACPI Specification constants (Do not change unless the specification changes)
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 84f5cb242863..a1ae1057d2ef 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -153,8 +153,9 @@
153#define AE_AML_CIRCULAR_REFERENCE (acpi_status) (0x001E | AE_CODE_AML) 153#define AE_AML_CIRCULAR_REFERENCE (acpi_status) (0x001E | AE_CODE_AML)
154#define AE_AML_BAD_RESOURCE_LENGTH (acpi_status) (0x001F | AE_CODE_AML) 154#define AE_AML_BAD_RESOURCE_LENGTH (acpi_status) (0x001F | AE_CODE_AML)
155#define AE_AML_ILLEGAL_ADDRESS (acpi_status) (0x0020 | AE_CODE_AML) 155#define AE_AML_ILLEGAL_ADDRESS (acpi_status) (0x0020 | AE_CODE_AML)
156#define AE_AML_INFINITE_LOOP (acpi_status) (0x0021 | AE_CODE_AML)
156 157
157#define AE_CODE_AML_MAX 0x0020 158#define AE_CODE_AML_MAX 0x0021
158 159
159/* 160/*
160 * Internal exceptions used for control 161 * Internal exceptions used for control
@@ -267,6 +268,7 @@ char const *acpi_gbl_exception_names_aml[] = {
267 "AE_AML_CIRCULAR_REFERENCE", 268 "AE_AML_CIRCULAR_REFERENCE",
268 "AE_AML_BAD_RESOURCE_LENGTH", 269 "AE_AML_BAD_RESOURCE_LENGTH",
269 "AE_AML_ILLEGAL_ADDRESS", 270 "AE_AML_ILLEGAL_ADDRESS",
271 "AE_AML_INFINITE_LOOP"
270}; 272};
271 273
272char const *acpi_gbl_exception_names_ctrl[] = { 274char const *acpi_gbl_exception_names_ctrl[] = {
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index ecab527cf78e..0323fa9aa3e6 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -566,6 +566,7 @@ struct acpi_control_state {
566 union acpi_parse_object *predicate_op; 566 union acpi_parse_object *predicate_op;
567 u8 *aml_predicate_start; /* Start of if/while predicate */ 567 u8 *aml_predicate_start; /* Start of if/while predicate */
568 u8 *package_end; /* End of if/while block */ 568 u8 *package_end; /* End of if/while block */
569 u32 loop_count; /* While() loop counter */
569}; 570};
570 571
571/* 572/*