summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2017-11-17 18:40:18 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-11-26 19:20:29 -0500
commit164a08cee1358e360c47fcb26a7720461d5853a5 (patch)
treeda44cdbbbe77db422208e3271e123dbf8468f28a
parent29ad1f88ab7dd6c220ff9f5b9faed718b443f4a4 (diff)
ACPICA: Dispatcher: Introduce timeout mechanism for infinite loop detection
ACPICA commit 9605023e7e6d1f05581502766c8cf2905bcc03d9 This patch implements a new infinite loop detection mechanism to replace the old one, it uses acpi_os_get_timer() to limit loop execution into a determined time slice. This is useful in case some hardware/firmware operations really require the AML interpreter to wait while the old mechanism could expire too fast on recent machines. The new mechanism converts old acpi_gbl_max_loop_iterations to store the user configurable value for the new mechanism in order to allow users to be still able to configure this value for acpiexec via command line. This patch also removes wrong initilization code of acpi_gbl_max_loop_iterations accordingly (it should have been initialized by ACPI_INIT_GLOBAL, and the default value is also properly tuned for acpiexec). Reported by M. Foronda, fixed by Lv Zheng. Link: https://github.com/acpica/acpica/commit/9605023e Link: https://bugzilla.kernel.org/show_bug.cgi?id=156501 Reported-by: M. Foronda <josemauricioforonda@gmail.com> Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Erik Schmauss <erik.schmauss@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/acpica/aclocal.h2
-rw-r--r--drivers/acpi/acpica/dscontrol.c16
-rw-r--r--drivers/acpi/acpica/utinit.c1
-rw-r--r--include/acpi/acconfig.h4
-rw-r--r--include/acpi/acpixf.h4
-rw-r--r--include/acpi/actypes.h2
6 files changed, 16 insertions, 13 deletions
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 0d45b8bb1678..bed041d41596 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -622,7 +622,7 @@ struct acpi_control_state {
622 union acpi_parse_object *predicate_op; 622 union acpi_parse_object *predicate_op;
623 u8 *aml_predicate_start; /* Start of if/while predicate */ 623 u8 *aml_predicate_start; /* Start of if/while predicate */
624 u8 *package_end; /* End of if/while block */ 624 u8 *package_end; /* End of if/while block */
625 u32 loop_count; /* While() loop counter */ 625 u64 loop_timeout; /* While() loop timeout */
626}; 626};
627 627
628/* 628/*
diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c
index f470e81b0499..244075dbc03a 100644
--- a/drivers/acpi/acpica/dscontrol.c
+++ b/drivers/acpi/acpica/dscontrol.c
@@ -118,6 +118,8 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
118 control_state->control.package_end = 118 control_state->control.package_end =
119 walk_state->parser_state.pkg_end; 119 walk_state->parser_state.pkg_end;
120 control_state->control.opcode = op->common.aml_opcode; 120 control_state->control.opcode = op->common.aml_opcode;
121 control_state->control.loop_timeout = acpi_os_get_timer() +
122 (u64)(acpi_gbl_max_loop_iterations * ACPI_100NSEC_PER_SEC);
121 123
122 /* Push the control state on this walk's control stack */ 124 /* Push the control state on this walk's control stack */
123 125
@@ -206,14 +208,14 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state,
206 /* Predicate was true, the body of the loop was just executed */ 208 /* Predicate was true, the body of the loop was just executed */
207 209
208 /* 210 /*
209 * This loop counter mechanism allows the interpreter to escape 211 * This infinite loop detection mechanism allows the interpreter
210 * possibly infinite loops. This can occur in poorly written AML 212 * to escape possibly infinite loops. This can occur in poorly
211 * when the hardware does not respond within a while loop and the 213 * written AML when the hardware does not respond within a while
212 * loop does not implement a timeout. 214 * loop and the loop does not implement a timeout.
213 */ 215 */
214 control_state->control.loop_count++; 216 if (ACPI_TIME_AFTER(acpi_os_get_timer(),
215 if (control_state->control.loop_count > 217 control_state->control.
216 acpi_gbl_max_loop_iterations) { 218 loop_timeout)) {
217 status = AE_AML_INFINITE_LOOP; 219 status = AE_AML_INFINITE_LOOP;
218 break; 220 break;
219 } 221 }
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c
index 23e766d1691d..45eeb0dcf283 100644
--- a/drivers/acpi/acpica/utinit.c
+++ b/drivers/acpi/acpica/utinit.c
@@ -206,7 +206,6 @@ acpi_status acpi_ut_init_globals(void)
206 acpi_gbl_next_owner_id_offset = 0; 206 acpi_gbl_next_owner_id_offset = 0;
207 acpi_gbl_debugger_configuration = DEBUGGER_THREADING; 207 acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
208 acpi_gbl_osi_mutex = NULL; 208 acpi_gbl_osi_mutex = NULL;
209 acpi_gbl_max_loop_iterations = ACPI_MAX_LOOP_COUNT;
210 209
211 /* Hardware oriented */ 210 /* Hardware oriented */
212 211
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 6db3b4668b1a..ffe364fa4040 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -145,9 +145,9 @@
145 145
146#define ACPI_ADDRESS_RANGE_MAX 2 146#define ACPI_ADDRESS_RANGE_MAX 2
147 147
148/* Maximum number of While() loops before abort */ 148/* Maximum time (default 30s) of While() loops before abort */
149 149
150#define ACPI_MAX_LOOP_COUNT 0x000FFFFF 150#define ACPI_MAX_LOOP_TIMEOUT 30
151 151
152/****************************************************************************** 152/******************************************************************************
153 * 153 *
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index e1dd1a8d42b6..1a4322db0274 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -260,11 +260,11 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_osi_data, 0);
260ACPI_INIT_GLOBAL(u8, acpi_gbl_reduced_hardware, FALSE); 260ACPI_INIT_GLOBAL(u8, acpi_gbl_reduced_hardware, FALSE);
261 261
262/* 262/*
263 * Maximum number of While() loop iterations before forced method abort. 263 * Maximum timeout for While() loop iterations before forced method abort.
264 * This mechanism is intended to prevent infinite loops during interpreter 264 * This mechanism is intended to prevent infinite loops during interpreter
265 * execution within a host kernel. 265 * execution within a host kernel.
266 */ 266 */
267ACPI_INIT_GLOBAL(u32, acpi_gbl_max_loop_iterations, ACPI_MAX_LOOP_COUNT); 267ACPI_INIT_GLOBAL(u32, acpi_gbl_max_loop_iterations, ACPI_MAX_LOOP_TIMEOUT);
268 268
269/* 269/*
270 * This mechanism is used to trace a specified AML method. The method is 270 * This mechanism is used to trace a specified AML method. The method is
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 4f077edb9b81..ddde2790a54a 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -468,6 +468,8 @@ typedef void *acpi_handle; /* Actually a ptr to a NS Node */
468#define ACPI_NSEC_PER_MSEC 1000000L 468#define ACPI_NSEC_PER_MSEC 1000000L
469#define ACPI_NSEC_PER_SEC 1000000000L 469#define ACPI_NSEC_PER_SEC 1000000000L
470 470
471#define ACPI_TIME_AFTER(a, b) ((s64)((b) - (a)) < 0)
472
471/* Owner IDs are used to track namespace nodes for selective deletion */ 473/* Owner IDs are used to track namespace nodes for selective deletion */
472 474
473typedef u8 acpi_owner_id; 475typedef u8 acpi_owner_id;