From 164a08cee1358e360c47fcb26a7720461d5853a5 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 17 Nov 2017 15:40:18 -0800 Subject: 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 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/aclocal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi/acpica/aclocal.h') 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 { union acpi_parse_object *predicate_op; u8 *aml_predicate_start; /* Start of if/while predicate */ u8 *package_end; /* End of if/while block */ - u32 loop_count; /* While() loop counter */ + u64 loop_timeout; /* While() loop timeout */ }; /* -- cgit v1.2.3 From 060c859d79ed8ead423a076e581af08d6496bf02 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 17 Nov 2017 15:42:26 -0800 Subject: ACPICA: Debugger: add "background" command for method execution ACPICA commit d7b44738a48caa9f669b8dbf0024d456711aec31 Allows a single task to execute in the background, while control returns to the debugger prompt. Also, cleanup the debugger help screen. Link: https://github.com/acpica/acpica/commit/d7b44738 Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acdebug.h | 4 ++ drivers/acpi/acpica/aclocal.h | 13 ++-- drivers/acpi/acpica/dbexec.c | 110 +++++++++++++++++++++++++++++++- drivers/acpi/acpica/dbinput.c | 145 +++++++++++++++++++++++++----------------- 4 files changed, 206 insertions(+), 66 deletions(-) (limited to 'drivers/acpi/acpica/aclocal.h') diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 71743e5252f5..54b8d9df9423 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -222,6 +222,10 @@ ACPI_DBR_DEPENDENT_RETURN_VOID(void void acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags); +void +acpi_db_create_execution_thread(char *method_name_arg, + char **arguments, acpi_object_type *types); + void acpi_db_create_execution_threads(char *num_threads_arg, char *num_loops_arg, char *method_name_arg); diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index bed041d41596..a56675f0661e 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -1218,16 +1218,17 @@ struct acpi_db_method_info { acpi_object_type *types; /* - * Arguments to be passed to method for the command - * Threads - - * the Number of threads, ID of current thread and - * Index of current thread inside all them created. + * Arguments to be passed to method for the commands Threads and + * Background. Note, ACPI specifies a maximum of 7 arguments (0 - 6). + * + * For the Threads command, the Number of threads, ID of current + * thread and Index of current thread inside all them created. */ char init_args; #ifdef ACPI_DEBUGGER - acpi_object_type arg_types[4]; + acpi_object_type arg_types[ACPI_METHOD_NUM_ARGS]; #endif - char *arguments[4]; + char *arguments[ACPI_METHOD_NUM_ARGS]; char num_threads_str[11]; char id_of_thread_str[11]; char index_of_thread_str[11]; diff --git a/drivers/acpi/acpica/dbexec.c b/drivers/acpi/acpica/dbexec.c index 3b30319752f0..ed088fceb18d 100644 --- a/drivers/acpi/acpica/dbexec.c +++ b/drivers/acpi/acpica/dbexec.c @@ -67,6 +67,8 @@ static acpi_status acpi_db_execution_walk(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value); +static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context); + /******************************************************************************* * * FUNCTION: acpi_db_delete_objects @@ -229,7 +231,7 @@ static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info) ACPI_FUNCTION_NAME(db_execute_setup); - /* Catenate the current scope to the supplied name */ + /* Concatenate the current scope to the supplied name */ info->pathname[0] = 0; if ((info->name[0] != '\\') && (info->name[0] != '/')) { @@ -609,6 +611,112 @@ static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context) } } +/******************************************************************************* + * + * FUNCTION: acpi_db_single_execution_thread + * + * PARAMETERS: context - Method info struct + * + * RETURN: None + * + * DESCRIPTION: Create one thread and execute a method + * + ******************************************************************************/ + +static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context) +{ + struct acpi_db_method_info *info = context; + acpi_status status; + struct acpi_buffer return_obj; + + acpi_os_printf("\n"); + + status = acpi_db_execute_method(info, &return_obj); + if (ACPI_FAILURE(status)) { + acpi_os_printf("%s During evaluation of %s\n", + acpi_format_exception(status), info->pathname); + return; + } + + /* Display a return object, if any */ + + if (return_obj.length) { + acpi_os_printf("Evaluation of %s returned object %p, " + "external buffer length %X\n", + acpi_gbl_db_method_info.pathname, + return_obj.pointer, (u32)return_obj.length); + + acpi_db_dump_external_object(return_obj.pointer, 1); + } + + acpi_os_printf("\nBackground thread completed\n%c ", + ACPI_DEBUGGER_COMMAND_PROMPT); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_create_execution_thread + * + * PARAMETERS: method_name_arg - Control method to execute + * arguments - Array of arguments to the method + * types - Corresponding array of object types + * + * RETURN: None + * + * DESCRIPTION: Create a single thread to evaluate a namespace object. Handles + * arguments passed on command line for control methods. + * + ******************************************************************************/ + +void +acpi_db_create_execution_thread(char *method_name_arg, + char **arguments, acpi_object_type *types) +{ + acpi_status status; + u32 i; + + memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info)); + acpi_gbl_db_method_info.name = method_name_arg; + acpi_gbl_db_method_info.init_args = 1; + acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments; + acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types; + + /* Setup method arguments, up to 7 (0-6) */ + + for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && *arguments; i++) { + acpi_gbl_db_method_info.arguments[i] = *arguments; + arguments++; + + acpi_gbl_db_method_info.arg_types[i] = *types; + types++; + } + + status = acpi_db_execute_setup(&acpi_gbl_db_method_info); + if (ACPI_FAILURE(status)) { + return; + } + + /* Get the NS node, determines existence also */ + + status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname, + &acpi_gbl_db_method_info.method); + if (ACPI_FAILURE(status)) { + acpi_os_printf("%s Could not get handle for %s\n", + acpi_format_exception(status), + acpi_gbl_db_method_info.pathname); + return; + } + + status = acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD, + acpi_db_single_execution_thread, + &acpi_gbl_db_method_info); + if (ACPI_FAILURE(status)) { + return; + } + + acpi_os_printf("\nBackground thread started\n"); +} + /******************************************************************************* * * FUNCTION: acpi_db_create_execution_threads diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c index 2626d79db064..954ca3b981a7 100644 --- a/drivers/acpi/acpica/dbinput.c +++ b/drivers/acpi/acpica/dbinput.c @@ -136,6 +136,7 @@ enum acpi_ex_debugger_commands { CMD_UNLOAD, CMD_TERMINATE, + CMD_BACKGROUND, CMD_THREADS, CMD_TEST, @@ -212,6 +213,7 @@ static const struct acpi_db_command_info acpi_gbl_db_commands[] = { {"UNLOAD", 1}, {"TERMINATE", 0}, + {"BACKGROUND", 1}, {"THREADS", 3}, {"TEST", 1}, @@ -222,9 +224,56 @@ static const struct acpi_db_command_info acpi_gbl_db_commands[] = { /* * Help for all debugger commands. First argument is the number of lines * of help to output for the command. + * + * Note: Some commands are not supported by the kernel-level version of + * the debugger. */ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = { - {0, "\nGeneral-Purpose Commands:", "\n"}, + {0, "\nNamespace Access:", "\n"}, + {1, " Businfo", "Display system bus info\n"}, + {1, " Disassemble ", "Disassemble a control method\n"}, + {1, " Find (? is wildcard)", + "Find ACPI name(s) with wildcards\n"}, + {1, " Integrity", "Validate namespace integrity\n"}, + {1, " Methods", "Display list of loaded control methods\n"}, + {1, " Namespace [Object] [Depth]", + "Display loaded namespace tree/subtree\n"}, + {1, " Notify ", "Send a notification on Object\n"}, + {1, " Objects [ObjectType]", + "Display summary of all objects or just given type\n"}, + {1, " Owner [Depth]", + "Display loaded namespace by object owner\n"}, + {1, " Paths", "Display full pathnames of namespace objects\n"}, + {1, " Predefined", "Check all predefined names\n"}, + {1, " Prefix []", "Set or Get current execution prefix\n"}, + {1, " References ", "Find all references to object at addr\n"}, + {1, " Resources [DeviceName]", + "Display Device resources (no arg = all devices)\n"}, + {1, " Set N ", "Set value for named integer\n"}, + {1, " Template ", "Format/dump a Buffer/ResourceTemplate\n"}, + {1, " Type ", "Display object type\n"}, + + {0, "\nControl Method Execution:", "\n"}, + {1, " Evaluate [Arguments]", + "Evaluate object or control method\n"}, + {1, " Execute [Arguments]", "Synonym for Evaluate\n"}, +#ifdef ACPI_APPLICATION + {1, " Background [Arguments]", + "Evaluate object/method in a separate thread\n"}, + {1, " Thread ", + "Spawn threads to execute method(s)\n"}, +#endif + {1, " Debug [Arguments]", "Single-Step a control method\n"}, + {7, " [Arguments] formats:", "Control method argument formats\n"}, + {1, " Hex Integer", "Integer\n"}, + {1, " \"Ascii String\"", "String\n"}, + {1, " (Hex Byte List)", "Buffer\n"}, + {1, " (01 42 7A BF)", "Buffer example (4 bytes)\n"}, + {1, " [Package Element List]", "Package\n"}, + {1, " [0x01 0x1234 \"string\"]", + "Package example (3 elements)\n"}, + + {0, "\nMiscellaneous:", "\n"}, {1, " Allocations", "Display list of current memory allocations\n"}, {2, " Dump
|", "\n"}, {0, " [Byte|Word|Dword|Qword]", @@ -248,46 +297,30 @@ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = { {1, " Stack", "Display CPU stack usage\n"}, {1, " Tables", "Info about current ACPI table(s)\n"}, {1, " Tables", "Display info about loaded ACPI tables\n"}, +#ifdef ACPI_APPLICATION + {1, " Terminate", "Delete namespace and all internal objects\n"}, +#endif {1, " ! ", "Execute command from history buffer\n"}, {1, " !!", "Execute last command again\n"}, - {0, "\nNamespace Access Commands:", "\n"}, - {1, " Businfo", "Display system bus info\n"}, - {1, " Disassemble ", "Disassemble a control method\n"}, - {1, " Find (? is wildcard)", - "Find ACPI name(s) with wildcards\n"}, - {1, " Integrity", "Validate namespace integrity\n"}, - {1, " Methods", "Display list of loaded control methods\n"}, - {1, " Namespace [Object] [Depth]", - "Display loaded namespace tree/subtree\n"}, - {1, " Notify ", "Send a notification on Object\n"}, - {1, " Objects [ObjectType]", - "Display summary of all objects or just given type\n"}, - {1, " Owner [Depth]", - "Display loaded namespace by object owner\n"}, - {1, " Paths", "Display full pathnames of namespace objects\n"}, - {1, " Predefined", "Check all predefined names\n"}, - {1, " Prefix []", "Set or Get current execution prefix\n"}, - {1, " References ", "Find all references to object at addr\n"}, - {1, " Resources [DeviceName]", - "Display Device resources (no arg = all devices)\n"}, - {1, " Set N ", "Set value for named integer\n"}, - {1, " Template ", "Format/dump a Buffer/ResourceTemplate\n"}, - {1, " Type ", "Display object type\n"}, + {0, "\nMethod and Namespace Debugging:", "\n"}, + {5, " Trace [] [Once]", + "Trace control method execution\n"}, + {1, " Enable", "Enable all messages\n"}, + {1, " Disable", "Disable tracing\n"}, + {1, " Method", "Enable method execution messages\n"}, + {1, " Opcode", "Enable opcode execution messages\n"}, + {3, " Test ", "Invoke a debug test\n"}, + {1, " Objects", "Read/write/compare all namespace data objects\n"}, + {1, " Predefined", + "Validate all ACPI predefined names (_STA, etc.)\n"}, + {1, " Execute predefined", + "Execute all predefined (public) methods\n"}, - {0, "\nControl Method Execution Commands:", "\n"}, + {0, "\nControl Method Single-Step Execution:", "\n"}, {1, " Arguments (or Args)", "Display method arguments\n"}, {1, " Breakpoint ", "Set an AML execution breakpoint\n"}, {1, " Call", "Run to next control method invocation\n"}, - {1, " Debug [Arguments]", "Single Step a control method\n"}, - {6, " Evaluate", "Synonym for Execute\n"}, - {5, " Execute [Arguments]", "Execute control method\n"}, - {1, " Hex Integer", "Integer method argument\n"}, - {1, " \"Ascii String\"", "String method argument\n"}, - {1, " (Hex Byte List)", "Buffer method argument\n"}, - {1, " [Package Element List]", "Package method argument\n"}, - {5, " Execute predefined", - "Execute all predefined (public) methods\n"}, {1, " Go", "Allow method to run to completion\n"}, {1, " Information", "Display info about the current method\n"}, {1, " Into", "Step into (not over) a method call\n"}, @@ -296,41 +329,24 @@ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = { {1, " Results", "Display method result stack\n"}, {1, " Set <#> ", "Set method data (Arguments/Locals)\n"}, {1, " Stop", "Terminate control method\n"}, - {5, " Trace [] [Once]", - "Trace control method execution\n"}, - {1, " Enable", "Enable all messages\n"}, - {1, " Disable", "Disable tracing\n"}, - {1, " Method", "Enable method execution messages\n"}, - {1, " Opcode", "Enable opcode execution messages\n"}, {1, " Tree", "Display control method calling tree\n"}, {1, " ", "Single step next AML opcode (over calls)\n"}, #ifdef ACPI_APPLICATION - {0, "\nHardware Simulation Commands:", "\n"}, - {1, " EnableAcpi", "Enable ACPI (hardware) mode\n"}, - {1, " Event ", "Generate AcpiEvent (Fixed/GPE)\n"}, - {1, " Gpe [GpeBlockDevice]", "Simulate a GPE\n"}, - {1, " Gpes", "Display info on all GPE devices\n"}, - {1, " Sci", "Generate an SCI\n"}, - {1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"}, - - {0, "\nFile I/O Commands:", "\n"}, + {0, "\nFile Operations:", "\n"}, {1, " Close", "Close debug output file\n"}, {1, " Load ", "Load ACPI table from a file\n"}, {1, " Open ", "Open a file for debug output\n"}, {1, " Unload ", "Unload an ACPI table via namespace object\n"}, - {0, "\nUser Space Commands:", "\n"}, - {1, " Terminate", "Delete namespace and all internal objects\n"}, - {1, " Thread ", - "Spawn threads to execute method(s)\n"}, - - {0, "\nDebug Test Commands:", "\n"}, - {3, " Test ", "Invoke a debug test\n"}, - {1, " Objects", "Read/write/compare all namespace data objects\n"}, - {1, " Predefined", - "Execute all ACPI predefined names (_STA, etc.)\n"}, + {0, "\nHardware Simulation:", "\n"}, + {1, " EnableAcpi", "Enable ACPI (hardware) mode\n"}, + {1, " Event ", "Generate AcpiEvent (Fixed/GPE)\n"}, + {1, " Gpe [GpeBlockDevice]", "Simulate a GPE\n"}, + {1, " Gpes", "Display info on all GPE devices\n"}, + {1, " Sci", "Generate an SCI\n"}, + {1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"}, #endif {0, NULL, NULL} }; @@ -442,11 +458,15 @@ static void acpi_db_display_help(char *command) /* No argument to help, display help for all commands */ + acpi_os_printf("\nSummary of AML Debugger Commands\n\n"); + while (next->invocation) { acpi_os_printf("%-38s%s", next->invocation, next->description); next++; } + acpi_os_printf("\n"); + } else { /* Display help for all commands that match the subtring */ @@ -1087,6 +1107,13 @@ acpi_db_command_dispatch(char *input_buffer, /* acpi_initialize (NULL); */ break; + case CMD_BACKGROUND: + + acpi_db_create_execution_thread(acpi_gbl_db_args[1], + &acpi_gbl_db_args[2], + &acpi_gbl_db_arg_types[2]); + break; + case CMD_THREADS: acpi_db_create_execution_threads(acpi_gbl_db_args[1], -- cgit v1.2.3