xref: /openbmc/linux/drivers/acpi/acpica/dbexec.c (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
299575102SLv Zheng /*******************************************************************************
399575102SLv Zheng  *
499575102SLv Zheng  * Module Name: dbexec - debugger control method execution
599575102SLv Zheng  *
699575102SLv Zheng  ******************************************************************************/
799575102SLv Zheng 
899575102SLv Zheng #include <acpi/acpi.h>
999575102SLv Zheng #include "accommon.h"
1099575102SLv Zheng #include "acdebug.h"
1199575102SLv Zheng #include "acnamesp.h"
1299575102SLv Zheng 
1399575102SLv Zheng #define _COMPONENT          ACPI_CA_DEBUGGER
1499575102SLv Zheng ACPI_MODULE_NAME("dbexec")
1599575102SLv Zheng 
1699575102SLv Zheng static struct acpi_db_method_info acpi_gbl_db_method_info;
1799575102SLv Zheng 
1899575102SLv Zheng /* Local prototypes */
1999575102SLv Zheng 
2099575102SLv Zheng static acpi_status
2199575102SLv Zheng acpi_db_execute_method(struct acpi_db_method_info *info,
2299575102SLv Zheng 		       struct acpi_buffer *return_obj);
2399575102SLv Zheng 
2499575102SLv Zheng static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info);
2599575102SLv Zheng 
2699575102SLv Zheng static u32 acpi_db_get_outstanding_allocations(void);
2799575102SLv Zheng 
2899575102SLv Zheng static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context);
2999575102SLv Zheng 
3099575102SLv Zheng static acpi_status
3199575102SLv Zheng acpi_db_execution_walk(acpi_handle obj_handle,
3299575102SLv Zheng 		       u32 nesting_level, void *context, void **return_value);
3399575102SLv Zheng 
34060c859dSBob Moore static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context);
35060c859dSBob Moore 
3699575102SLv Zheng /*******************************************************************************
3799575102SLv Zheng  *
3899575102SLv Zheng  * FUNCTION:    acpi_db_delete_objects
3999575102SLv Zheng  *
4099575102SLv Zheng  * PARAMETERS:  count               - Count of objects in the list
4199575102SLv Zheng  *              objects             - Array of ACPI_OBJECTs to be deleted
4299575102SLv Zheng  *
4399575102SLv Zheng  * RETURN:      None
4499575102SLv Zheng  *
4599575102SLv Zheng  * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested
4699575102SLv Zheng  *              packages via recursion.
4799575102SLv Zheng  *
4899575102SLv Zheng  ******************************************************************************/
4999575102SLv Zheng 
acpi_db_delete_objects(u32 count,union acpi_object * objects)5099575102SLv Zheng void acpi_db_delete_objects(u32 count, union acpi_object *objects)
5199575102SLv Zheng {
5299575102SLv Zheng 	u32 i;
5399575102SLv Zheng 
5499575102SLv Zheng 	for (i = 0; i < count; i++) {
5599575102SLv Zheng 		switch (objects[i].type) {
5699575102SLv Zheng 		case ACPI_TYPE_BUFFER:
5799575102SLv Zheng 
5899575102SLv Zheng 			ACPI_FREE(objects[i].buffer.pointer);
5999575102SLv Zheng 			break;
6099575102SLv Zheng 
6199575102SLv Zheng 		case ACPI_TYPE_PACKAGE:
6299575102SLv Zheng 
6399575102SLv Zheng 			/* Recursive call to delete package elements */
6499575102SLv Zheng 
6599575102SLv Zheng 			acpi_db_delete_objects(objects[i].package.count,
6699575102SLv Zheng 					       objects[i].package.elements);
6799575102SLv Zheng 
6899575102SLv Zheng 			/* Free the elements array */
6999575102SLv Zheng 
7099575102SLv Zheng 			ACPI_FREE(objects[i].package.elements);
7199575102SLv Zheng 			break;
7299575102SLv Zheng 
7399575102SLv Zheng 		default:
7499575102SLv Zheng 
7599575102SLv Zheng 			break;
7699575102SLv Zheng 		}
7799575102SLv Zheng 	}
7899575102SLv Zheng }
7999575102SLv Zheng 
8099575102SLv Zheng /*******************************************************************************
8199575102SLv Zheng  *
8299575102SLv Zheng  * FUNCTION:    acpi_db_execute_method
8399575102SLv Zheng  *
8499575102SLv Zheng  * PARAMETERS:  info            - Valid info segment
8599575102SLv Zheng  *              return_obj      - Where to put return object
8699575102SLv Zheng  *
8799575102SLv Zheng  * RETURN:      Status
8899575102SLv Zheng  *
89*6218ab30SBob Moore  * DESCRIPTION: Execute a control method. Used to evaluate objects via the
90*6218ab30SBob Moore  *              "EXECUTE" or "EVALUATE" commands.
9199575102SLv Zheng  *
9299575102SLv Zheng  ******************************************************************************/
9399575102SLv Zheng 
9499575102SLv Zheng static acpi_status
acpi_db_execute_method(struct acpi_db_method_info * info,struct acpi_buffer * return_obj)9599575102SLv Zheng acpi_db_execute_method(struct acpi_db_method_info *info,
9699575102SLv Zheng 		       struct acpi_buffer *return_obj)
9799575102SLv Zheng {
9899575102SLv Zheng 	acpi_status status;
9999575102SLv Zheng 	struct acpi_object_list param_objects;
10099575102SLv Zheng 	union acpi_object params[ACPI_DEBUGGER_MAX_ARGS + 1];
10199575102SLv Zheng 	u32 i;
10299575102SLv Zheng 
10399575102SLv Zheng 	ACPI_FUNCTION_TRACE(db_execute_method);
10499575102SLv Zheng 
10599575102SLv Zheng 	if (acpi_gbl_db_output_to_file && !acpi_dbg_level) {
10699575102SLv Zheng 		acpi_os_printf("Warning: debug output is not enabled!\n");
10799575102SLv Zheng 	}
10899575102SLv Zheng 
10999575102SLv Zheng 	param_objects.count = 0;
11099575102SLv Zheng 	param_objects.pointer = NULL;
11199575102SLv Zheng 
11299575102SLv Zheng 	/* Pass through any command-line arguments */
11399575102SLv Zheng 
11499575102SLv Zheng 	if (info->args && info->args[0]) {
11599575102SLv Zheng 
11699575102SLv Zheng 		/* Get arguments passed on the command line */
11799575102SLv Zheng 
11899575102SLv Zheng 		for (i = 0; (info->args[i] && *(info->args[i])); i++) {
11999575102SLv Zheng 
12099575102SLv Zheng 			/* Convert input string (token) to an actual union acpi_object */
12199575102SLv Zheng 
12299575102SLv Zheng 			status = acpi_db_convert_to_object(info->types[i],
12399575102SLv Zheng 							   info->args[i],
12499575102SLv Zheng 							   &params[i]);
12599575102SLv Zheng 			if (ACPI_FAILURE(status)) {
12699575102SLv Zheng 				ACPI_EXCEPTION((AE_INFO, status,
12799575102SLv Zheng 						"While parsing method arguments"));
12899575102SLv Zheng 				goto cleanup;
12999575102SLv Zheng 			}
13099575102SLv Zheng 		}
13199575102SLv Zheng 
13299575102SLv Zheng 		param_objects.count = i;
13399575102SLv Zheng 		param_objects.pointer = params;
13499575102SLv Zheng 	}
13599575102SLv Zheng 
13699575102SLv Zheng 	/* Prepare for a return object of arbitrary size */
13799575102SLv Zheng 
13899575102SLv Zheng 	return_obj->pointer = acpi_gbl_db_buffer;
13999575102SLv Zheng 	return_obj->length = ACPI_DEBUG_BUFFER_SIZE;
14099575102SLv Zheng 
14199575102SLv Zheng 	/* Do the actual method execution */
14299575102SLv Zheng 
14399575102SLv Zheng 	acpi_gbl_method_executing = TRUE;
14499575102SLv Zheng 	status = acpi_evaluate_object(NULL, info->pathname,
14599575102SLv Zheng 				      &param_objects, return_obj);
14699575102SLv Zheng 
14799575102SLv Zheng 	acpi_gbl_cm_single_step = FALSE;
14899575102SLv Zheng 	acpi_gbl_method_executing = FALSE;
14999575102SLv Zheng 
15099575102SLv Zheng 	if (ACPI_FAILURE(status)) {
151fd13aaa8SBob Moore 		if ((status == AE_ABORT_METHOD) || acpi_gbl_abort_method) {
152fd13aaa8SBob Moore 
153fd13aaa8SBob Moore 			/* Clear the abort and fall back to the debugger prompt */
154fd13aaa8SBob Moore 
155fd13aaa8SBob Moore 			ACPI_EXCEPTION((AE_INFO, status,
156fd13aaa8SBob Moore 					"Aborting top-level method"));
157fd13aaa8SBob Moore 
158fd13aaa8SBob Moore 			acpi_gbl_abort_method = FALSE;
159fd13aaa8SBob Moore 			status = AE_OK;
160fd13aaa8SBob Moore 			goto cleanup;
161fd13aaa8SBob Moore 		}
162fd13aaa8SBob Moore 
16399575102SLv Zheng 		ACPI_EXCEPTION((AE_INFO, status,
164991371e0SBob Moore 				"while executing %s from AML Debugger",
16599575102SLv Zheng 				info->pathname));
16699575102SLv Zheng 
16799575102SLv Zheng 		if (status == AE_BUFFER_OVERFLOW) {
16899575102SLv Zheng 			ACPI_ERROR((AE_INFO,
169991371e0SBob Moore 				    "Possible buffer overflow within AML Debugger "
17099575102SLv Zheng 				    "buffer (size 0x%X needed 0x%X)",
17199575102SLv Zheng 				    ACPI_DEBUG_BUFFER_SIZE,
17299575102SLv Zheng 				    (u32)return_obj->length));
17399575102SLv Zheng 		}
17499575102SLv Zheng 	}
17599575102SLv Zheng 
17699575102SLv Zheng cleanup:
17799575102SLv Zheng 	acpi_db_delete_objects(param_objects.count, params);
17899575102SLv Zheng 	return_ACPI_STATUS(status);
17999575102SLv Zheng }
18099575102SLv Zheng 
18199575102SLv Zheng /*******************************************************************************
18299575102SLv Zheng  *
18399575102SLv Zheng  * FUNCTION:    acpi_db_execute_setup
18499575102SLv Zheng  *
18599575102SLv Zheng  * PARAMETERS:  info            - Valid method info
18699575102SLv Zheng  *
18799575102SLv Zheng  * RETURN:      None
18899575102SLv Zheng  *
18999575102SLv Zheng  * DESCRIPTION: Setup info segment prior to method execution
19099575102SLv Zheng  *
19199575102SLv Zheng  ******************************************************************************/
19299575102SLv Zheng 
acpi_db_execute_setup(struct acpi_db_method_info * info)19399575102SLv Zheng static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info)
19499575102SLv Zheng {
19599575102SLv Zheng 	acpi_status status;
19699575102SLv Zheng 
19799575102SLv Zheng 	ACPI_FUNCTION_NAME(db_execute_setup);
19899575102SLv Zheng 
199060c859dSBob Moore 	/* Concatenate the current scope to the supplied name */
20099575102SLv Zheng 
20199575102SLv Zheng 	info->pathname[0] = 0;
20299575102SLv Zheng 	if ((info->name[0] != '\\') && (info->name[0] != '/')) {
20399575102SLv Zheng 		if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
20499575102SLv Zheng 					acpi_gbl_db_scope_buf)) {
20599575102SLv Zheng 			status = AE_BUFFER_OVERFLOW;
20699575102SLv Zheng 			goto error_exit;
20799575102SLv Zheng 		}
20899575102SLv Zheng 	}
20999575102SLv Zheng 
21099575102SLv Zheng 	if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname),
21199575102SLv Zheng 				info->name)) {
21299575102SLv Zheng 		status = AE_BUFFER_OVERFLOW;
21399575102SLv Zheng 		goto error_exit;
21499575102SLv Zheng 	}
21599575102SLv Zheng 
21699575102SLv Zheng 	acpi_db_prep_namestring(info->pathname);
21799575102SLv Zheng 
21899575102SLv Zheng 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
21999575102SLv Zheng 	acpi_os_printf("Evaluating %s\n", info->pathname);
22099575102SLv Zheng 
22199575102SLv Zheng 	if (info->flags & EX_SINGLE_STEP) {
22299575102SLv Zheng 		acpi_gbl_cm_single_step = TRUE;
22399575102SLv Zheng 		acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
22499575102SLv Zheng 	}
22599575102SLv Zheng 
22699575102SLv Zheng 	else {
22799575102SLv Zheng 		/* No single step, allow redirection to a file */
22899575102SLv Zheng 
22999575102SLv Zheng 		acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
23099575102SLv Zheng 	}
23199575102SLv Zheng 
23299575102SLv Zheng 	return (AE_OK);
23399575102SLv Zheng 
23499575102SLv Zheng error_exit:
23599575102SLv Zheng 
23699575102SLv Zheng 	ACPI_EXCEPTION((AE_INFO, status, "During setup for method execution"));
23799575102SLv Zheng 	return (status);
23899575102SLv Zheng }
23999575102SLv Zheng 
24099575102SLv Zheng #ifdef ACPI_DBG_TRACK_ALLOCATIONS
acpi_db_get_cache_info(struct acpi_memory_list * cache)24199575102SLv Zheng u32 acpi_db_get_cache_info(struct acpi_memory_list *cache)
24299575102SLv Zheng {
24399575102SLv Zheng 
24499575102SLv Zheng 	return (cache->total_allocated - cache->total_freed -
24599575102SLv Zheng 		cache->current_depth);
24699575102SLv Zheng }
24799575102SLv Zheng #endif
24899575102SLv Zheng 
24999575102SLv Zheng /*******************************************************************************
25099575102SLv Zheng  *
25199575102SLv Zheng  * FUNCTION:    acpi_db_get_outstanding_allocations
25299575102SLv Zheng  *
25399575102SLv Zheng  * PARAMETERS:  None
25499575102SLv Zheng  *
25599575102SLv Zheng  * RETURN:      Current global allocation count minus cache entries
25699575102SLv Zheng  *
25799575102SLv Zheng  * DESCRIPTION: Determine the current number of "outstanding" allocations --
25899575102SLv Zheng  *              those allocations that have not been freed and also are not
25999575102SLv Zheng  *              in one of the various object caches.
26099575102SLv Zheng  *
26199575102SLv Zheng  ******************************************************************************/
26299575102SLv Zheng 
acpi_db_get_outstanding_allocations(void)26399575102SLv Zheng static u32 acpi_db_get_outstanding_allocations(void)
26499575102SLv Zheng {
26599575102SLv Zheng 	u32 outstanding = 0;
26699575102SLv Zheng 
26799575102SLv Zheng #ifdef ACPI_DBG_TRACK_ALLOCATIONS
26899575102SLv Zheng 
26999575102SLv Zheng 	outstanding += acpi_db_get_cache_info(acpi_gbl_state_cache);
27099575102SLv Zheng 	outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_cache);
27199575102SLv Zheng 	outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_ext_cache);
27299575102SLv Zheng 	outstanding += acpi_db_get_cache_info(acpi_gbl_operand_cache);
27399575102SLv Zheng #endif
27499575102SLv Zheng 
27599575102SLv Zheng 	return (outstanding);
27699575102SLv Zheng }
27799575102SLv Zheng 
27899575102SLv Zheng /*******************************************************************************
27999575102SLv Zheng  *
28099575102SLv Zheng  * FUNCTION:    acpi_db_execution_walk
28199575102SLv Zheng  *
28299575102SLv Zheng  * PARAMETERS:  WALK_CALLBACK
28399575102SLv Zheng  *
28499575102SLv Zheng  * RETURN:      Status
28599575102SLv Zheng  *
28699575102SLv Zheng  * DESCRIPTION: Execute a control method. Name is relative to the current
28799575102SLv Zheng  *              scope.
28899575102SLv Zheng  *
28999575102SLv Zheng  ******************************************************************************/
29099575102SLv Zheng 
29199575102SLv Zheng static acpi_status
acpi_db_execution_walk(acpi_handle obj_handle,u32 nesting_level,void * context,void ** return_value)29299575102SLv Zheng acpi_db_execution_walk(acpi_handle obj_handle,
29399575102SLv Zheng 		       u32 nesting_level, void *context, void **return_value)
29499575102SLv Zheng {
29599575102SLv Zheng 	union acpi_operand_object *obj_desc;
29699575102SLv Zheng 	struct acpi_namespace_node *node =
29799575102SLv Zheng 	    (struct acpi_namespace_node *)obj_handle;
29899575102SLv Zheng 	struct acpi_buffer return_obj;
29999575102SLv Zheng 	acpi_status status;
30099575102SLv Zheng 
30199575102SLv Zheng 	obj_desc = acpi_ns_get_attached_object(node);
30299575102SLv Zheng 	if (obj_desc->method.param_count) {
30399575102SLv Zheng 		return (AE_OK);
30499575102SLv Zheng 	}
30599575102SLv Zheng 
30699575102SLv Zheng 	return_obj.pointer = NULL;
30799575102SLv Zheng 	return_obj.length = ACPI_ALLOCATE_BUFFER;
30899575102SLv Zheng 
30999575102SLv Zheng 	acpi_ns_print_node_pathname(node, "Evaluating");
31099575102SLv Zheng 
31199575102SLv Zheng 	/* Do the actual method execution */
31299575102SLv Zheng 
31399575102SLv Zheng 	acpi_os_printf("\n");
31499575102SLv Zheng 	acpi_gbl_method_executing = TRUE;
31599575102SLv Zheng 
31699575102SLv Zheng 	status = acpi_evaluate_object(node, NULL, NULL, &return_obj);
31799575102SLv Zheng 
318*6218ab30SBob Moore 	acpi_gbl_method_executing = FALSE;
319*6218ab30SBob Moore 
32099575102SLv Zheng 	acpi_os_printf("Evaluation of [%4.4s] returned %s\n",
32199575102SLv Zheng 		       acpi_ut_get_node_name(node),
32299575102SLv Zheng 		       acpi_format_exception(status));
32399575102SLv Zheng 
32499575102SLv Zheng 	return (AE_OK);
32599575102SLv Zheng }
32699575102SLv Zheng 
32799575102SLv Zheng /*******************************************************************************
32899575102SLv Zheng  *
32999575102SLv Zheng  * FUNCTION:    acpi_db_execute
33099575102SLv Zheng  *
33199575102SLv Zheng  * PARAMETERS:  name                - Name of method to execute
33299575102SLv Zheng  *              args                - Parameters to the method
33399575102SLv Zheng  *              Types               -
33499575102SLv Zheng  *              flags               - single step/no single step
33599575102SLv Zheng  *
33699575102SLv Zheng  * RETURN:      None
33799575102SLv Zheng  *
33899575102SLv Zheng  * DESCRIPTION: Execute a control method. Name is relative to the current
339*6218ab30SBob Moore  *              scope. Function used for the "EXECUTE", "EVALUATE", and
340*6218ab30SBob Moore  *              "ALL" commands
34199575102SLv Zheng  *
34299575102SLv Zheng  ******************************************************************************/
34399575102SLv Zheng 
34499575102SLv Zheng void
acpi_db_execute(char * name,char ** args,acpi_object_type * types,u32 flags)34599575102SLv Zheng acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags)
34699575102SLv Zheng {
34799575102SLv Zheng 	acpi_status status;
34899575102SLv Zheng 	struct acpi_buffer return_obj;
34999575102SLv Zheng 	char *name_string;
35099575102SLv Zheng 
35199575102SLv Zheng #ifdef ACPI_DEBUG_OUTPUT
35299575102SLv Zheng 	u32 previous_allocations;
35399575102SLv Zheng 	u32 allocations;
354aaa93a61SLv Zheng #endif
35599575102SLv Zheng 
356aaa93a61SLv Zheng 	/*
357aaa93a61SLv Zheng 	 * Allow one execution to be performed by debugger or single step
358aaa93a61SLv Zheng 	 * execution will be dead locked by the interpreter mutexes.
359aaa93a61SLv Zheng 	 */
360aaa93a61SLv Zheng 	if (acpi_gbl_method_executing) {
361aaa93a61SLv Zheng 		acpi_os_printf("Only one debugger execution is allowed.\n");
362aaa93a61SLv Zheng 		return;
363aaa93a61SLv Zheng 	}
364aaa93a61SLv Zheng #ifdef ACPI_DEBUG_OUTPUT
36599575102SLv Zheng 	/* Memory allocation tracking */
36699575102SLv Zheng 
36799575102SLv Zheng 	previous_allocations = acpi_db_get_outstanding_allocations();
36899575102SLv Zheng #endif
36999575102SLv Zheng 
37099575102SLv Zheng 	if (*name == '*') {
37199575102SLv Zheng 		(void)acpi_walk_namespace(ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,
37299575102SLv Zheng 					  ACPI_UINT32_MAX,
37399575102SLv Zheng 					  acpi_db_execution_walk, NULL, NULL,
37499575102SLv Zheng 					  NULL);
37599575102SLv Zheng 		return;
37660361b75SBob Moore 	}
37760361b75SBob Moore 
378*6218ab30SBob Moore 	if ((flags & EX_ALL) && (strlen(name) > 4)) {
379*6218ab30SBob Moore 		acpi_os_printf("Input name (%s) must be a 4-char NameSeg\n",
380*6218ab30SBob Moore 			       name);
381*6218ab30SBob Moore 		return;
382*6218ab30SBob Moore 	}
383*6218ab30SBob Moore 
38499575102SLv Zheng 	name_string = ACPI_ALLOCATE(strlen(name) + 1);
38599575102SLv Zheng 	if (!name_string) {
38699575102SLv Zheng 		return;
38799575102SLv Zheng 	}
38899575102SLv Zheng 
38960361b75SBob Moore 	memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
39099575102SLv Zheng 	strcpy(name_string, name);
39199575102SLv Zheng 	acpi_ut_strupr(name_string);
39260361b75SBob Moore 
39360361b75SBob Moore 	/* Subcommand to Execute all predefined names in the namespace */
39460361b75SBob Moore 
39560361b75SBob Moore 	if (!strncmp(name_string, "PREDEF", 6)) {
39660361b75SBob Moore 		acpi_db_evaluate_predefined_names();
39760361b75SBob Moore 		ACPI_FREE(name_string);
39860361b75SBob Moore 		return;
39960361b75SBob Moore 	}
40060361b75SBob Moore 
401*6218ab30SBob Moore 	/* Command (ALL <nameseg>) to execute all methods of a particular name */
402*6218ab30SBob Moore 
403*6218ab30SBob Moore 	else if (flags & EX_ALL) {
404*6218ab30SBob Moore 		acpi_gbl_db_method_info.name = name_string;
405*6218ab30SBob Moore 		return_obj.pointer = NULL;
406*6218ab30SBob Moore 		return_obj.length = ACPI_ALLOCATE_BUFFER;
407*6218ab30SBob Moore 		acpi_db_evaluate_all(name_string);
408*6218ab30SBob Moore 		ACPI_FREE(name_string);
409*6218ab30SBob Moore 		return;
410*6218ab30SBob Moore 	} else {
41199575102SLv Zheng 		acpi_gbl_db_method_info.name = name_string;
41299575102SLv Zheng 		acpi_gbl_db_method_info.args = args;
41399575102SLv Zheng 		acpi_gbl_db_method_info.types = types;
41499575102SLv Zheng 		acpi_gbl_db_method_info.flags = flags;
41599575102SLv Zheng 
41699575102SLv Zheng 		return_obj.pointer = NULL;
41799575102SLv Zheng 		return_obj.length = ACPI_ALLOCATE_BUFFER;
418*6218ab30SBob Moore 	}
41999575102SLv Zheng 
42099575102SLv Zheng 	status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
42199575102SLv Zheng 	if (ACPI_FAILURE(status)) {
42299575102SLv Zheng 		ACPI_FREE(name_string);
42399575102SLv Zheng 		return;
42499575102SLv Zheng 	}
42599575102SLv Zheng 
42699575102SLv Zheng 	/* Get the NS node, determines existence also */
42799575102SLv Zheng 
42899575102SLv Zheng 	status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
42999575102SLv Zheng 				 &acpi_gbl_db_method_info.method);
43099575102SLv Zheng 	if (ACPI_SUCCESS(status)) {
43160361b75SBob Moore 		status = acpi_db_execute_method(&acpi_gbl_db_method_info,
43299575102SLv Zheng 						&return_obj);
43399575102SLv Zheng 	}
43499575102SLv Zheng 	ACPI_FREE(name_string);
43599575102SLv Zheng 
43699575102SLv Zheng 	/*
43799575102SLv Zheng 	 * Allow any handlers in separate threads to complete.
43899575102SLv Zheng 	 * (Such as Notify handlers invoked from AML executed above).
43999575102SLv Zheng 	 */
44099575102SLv Zheng 	acpi_os_sleep((u64)10);
44199575102SLv Zheng 
44299575102SLv Zheng #ifdef ACPI_DEBUG_OUTPUT
44399575102SLv Zheng 
44499575102SLv Zheng 	/* Memory allocation tracking */
44599575102SLv Zheng 
44699575102SLv Zheng 	allocations =
44799575102SLv Zheng 	    acpi_db_get_outstanding_allocations() - previous_allocations;
44899575102SLv Zheng 
44999575102SLv Zheng 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
45099575102SLv Zheng 
45199575102SLv Zheng 	if (allocations > 0) {
45299575102SLv Zheng 		acpi_os_printf
45399575102SLv Zheng 		    ("0x%X Outstanding allocations after evaluation of %s\n",
45499575102SLv Zheng 		     allocations, acpi_gbl_db_method_info.pathname);
45599575102SLv Zheng 	}
45699575102SLv Zheng #endif
45799575102SLv Zheng 
45899575102SLv Zheng 	if (ACPI_FAILURE(status)) {
45999575102SLv Zheng 		acpi_os_printf("Evaluation of %s failed with status %s\n",
46099575102SLv Zheng 			       acpi_gbl_db_method_info.pathname,
46199575102SLv Zheng 			       acpi_format_exception(status));
46299575102SLv Zheng 	} else {
46399575102SLv Zheng 		/* Display a return object, if any */
46499575102SLv Zheng 
46599575102SLv Zheng 		if (return_obj.length) {
46699575102SLv Zheng 			acpi_os_printf("Evaluation of %s returned object %p, "
46799575102SLv Zheng 				       "external buffer length %X\n",
46899575102SLv Zheng 				       acpi_gbl_db_method_info.pathname,
46999575102SLv Zheng 				       return_obj.pointer,
47099575102SLv Zheng 				       (u32)return_obj.length);
47199575102SLv Zheng 
47299575102SLv Zheng 			acpi_db_dump_external_object(return_obj.pointer, 1);
473*6218ab30SBob Moore 			acpi_os_printf("\n");
47499575102SLv Zheng 
47599575102SLv Zheng 			/* Dump a _PLD buffer if present */
47699575102SLv Zheng 
4775599fb69SBob Moore 			if (ACPI_COMPARE_NAMESEG
47899575102SLv Zheng 			    ((ACPI_CAST_PTR
47999575102SLv Zheng 			      (struct acpi_namespace_node,
48099575102SLv Zheng 			       acpi_gbl_db_method_info.method)->name.ascii),
48199575102SLv Zheng 			     METHOD_NAME__PLD)) {
48299575102SLv Zheng 				acpi_db_dump_pld_buffer(return_obj.pointer);
48399575102SLv Zheng 			}
48499575102SLv Zheng 		} else {
48599575102SLv Zheng 			acpi_os_printf
48699575102SLv Zheng 			    ("No object was returned from evaluation of %s\n",
48799575102SLv Zheng 			     acpi_gbl_db_method_info.pathname);
48899575102SLv Zheng 		}
48999575102SLv Zheng 	}
49099575102SLv Zheng 
49199575102SLv Zheng 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
49299575102SLv Zheng }
49399575102SLv Zheng 
49499575102SLv Zheng /*******************************************************************************
49599575102SLv Zheng  *
49699575102SLv Zheng  * FUNCTION:    acpi_db_method_thread
49799575102SLv Zheng  *
49899575102SLv Zheng  * PARAMETERS:  context             - Execution info segment
49999575102SLv Zheng  *
50099575102SLv Zheng  * RETURN:      None
50199575102SLv Zheng  *
50299575102SLv Zheng  * DESCRIPTION: Debugger execute thread. Waits for a command line, then
50399575102SLv Zheng  *              simply dispatches it.
50499575102SLv Zheng  *
50599575102SLv Zheng  ******************************************************************************/
50699575102SLv Zheng 
acpi_db_method_thread(void * context)50799575102SLv Zheng static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context)
50899575102SLv Zheng {
50999575102SLv Zheng 	acpi_status status;
51099575102SLv Zheng 	struct acpi_db_method_info *info = context;
51199575102SLv Zheng 	struct acpi_db_method_info local_info;
51299575102SLv Zheng 	u32 i;
51399575102SLv Zheng 	u8 allow;
51499575102SLv Zheng 	struct acpi_buffer return_obj;
51599575102SLv Zheng 
51699575102SLv Zheng 	/*
51799575102SLv Zheng 	 * acpi_gbl_db_method_info.Arguments will be passed as method arguments.
51899575102SLv Zheng 	 * Prevent acpi_gbl_db_method_info from being modified by multiple threads
51999575102SLv Zheng 	 * concurrently.
52099575102SLv Zheng 	 *
52199575102SLv Zheng 	 * Note: The arguments we are passing are used by the ASL test suite
52299575102SLv Zheng 	 * (aslts). Do not change them without updating the tests.
52399575102SLv Zheng 	 */
52499575102SLv Zheng 	(void)acpi_os_wait_semaphore(info->info_gate, 1, ACPI_WAIT_FOREVER);
52599575102SLv Zheng 
52699575102SLv Zheng 	if (info->init_args) {
52799575102SLv Zheng 		acpi_db_uint32_to_hex_string(info->num_created,
52899575102SLv Zheng 					     info->index_of_thread_str);
52999575102SLv Zheng 		acpi_db_uint32_to_hex_string((u32)acpi_os_get_thread_id(),
53099575102SLv Zheng 					     info->id_of_thread_str);
53199575102SLv Zheng 	}
53299575102SLv Zheng 
53399575102SLv Zheng 	if (info->threads && (info->num_created < info->num_threads)) {
53499575102SLv Zheng 		info->threads[info->num_created++] = acpi_os_get_thread_id();
53599575102SLv Zheng 	}
53699575102SLv Zheng 
53799575102SLv Zheng 	local_info = *info;
53899575102SLv Zheng 	local_info.args = local_info.arguments;
53999575102SLv Zheng 	local_info.arguments[0] = local_info.num_threads_str;
54099575102SLv Zheng 	local_info.arguments[1] = local_info.id_of_thread_str;
54199575102SLv Zheng 	local_info.arguments[2] = local_info.index_of_thread_str;
54299575102SLv Zheng 	local_info.arguments[3] = NULL;
54399575102SLv Zheng 
54499575102SLv Zheng 	local_info.types = local_info.arg_types;
54599575102SLv Zheng 
54699575102SLv Zheng 	(void)acpi_os_signal_semaphore(info->info_gate, 1);
54799575102SLv Zheng 
54899575102SLv Zheng 	for (i = 0; i < info->num_loops; i++) {
54999575102SLv Zheng 		status = acpi_db_execute_method(&local_info, &return_obj);
55099575102SLv Zheng 		if (ACPI_FAILURE(status)) {
55199575102SLv Zheng 			acpi_os_printf
55299575102SLv Zheng 			    ("%s During evaluation of %s at iteration %X\n",
55399575102SLv Zheng 			     acpi_format_exception(status), info->pathname, i);
55499575102SLv Zheng 			if (status == AE_ABORT_METHOD) {
55599575102SLv Zheng 				break;
55699575102SLv Zheng 			}
55799575102SLv Zheng 		}
55899575102SLv Zheng #if 0
55999575102SLv Zheng 		if ((i % 100) == 0) {
56099575102SLv Zheng 			acpi_os_printf("%u loops, Thread 0x%x\n",
56199575102SLv Zheng 				       i, acpi_os_get_thread_id());
56299575102SLv Zheng 		}
56399575102SLv Zheng 
56499575102SLv Zheng 		if (return_obj.length) {
56599575102SLv Zheng 			acpi_os_printf
56699575102SLv Zheng 			    ("Evaluation of %s returned object %p Buflen %X\n",
56799575102SLv Zheng 			     info->pathname, return_obj.pointer,
56899575102SLv Zheng 			     (u32)return_obj.length);
56999575102SLv Zheng 			acpi_db_dump_external_object(return_obj.pointer, 1);
57099575102SLv Zheng 		}
57199575102SLv Zheng #endif
57299575102SLv Zheng 	}
57399575102SLv Zheng 
57499575102SLv Zheng 	/* Signal our completion */
57599575102SLv Zheng 
57699575102SLv Zheng 	allow = 0;
57799575102SLv Zheng 	(void)acpi_os_wait_semaphore(info->thread_complete_gate,
57899575102SLv Zheng 				     1, ACPI_WAIT_FOREVER);
57999575102SLv Zheng 	info->num_completed++;
58099575102SLv Zheng 
58199575102SLv Zheng 	if (info->num_completed == info->num_threads) {
58299575102SLv Zheng 
58399575102SLv Zheng 		/* Do signal for main thread once only */
58499575102SLv Zheng 		allow = 1;
58599575102SLv Zheng 	}
58699575102SLv Zheng 
58799575102SLv Zheng 	(void)acpi_os_signal_semaphore(info->thread_complete_gate, 1);
58899575102SLv Zheng 
58999575102SLv Zheng 	if (allow) {
59099575102SLv Zheng 		status = acpi_os_signal_semaphore(info->main_thread_gate, 1);
59199575102SLv Zheng 		if (ACPI_FAILURE(status)) {
59299575102SLv Zheng 			acpi_os_printf
59399575102SLv Zheng 			    ("Could not signal debugger thread sync semaphore, %s\n",
59499575102SLv Zheng 			     acpi_format_exception(status));
59599575102SLv Zheng 		}
59699575102SLv Zheng 	}
59799575102SLv Zheng }
59899575102SLv Zheng 
59999575102SLv Zheng /*******************************************************************************
60099575102SLv Zheng  *
601060c859dSBob Moore  * FUNCTION:    acpi_db_single_execution_thread
602060c859dSBob Moore  *
603060c859dSBob Moore  * PARAMETERS:  context                 - Method info struct
604060c859dSBob Moore  *
605060c859dSBob Moore  * RETURN:      None
606060c859dSBob Moore  *
607060c859dSBob Moore  * DESCRIPTION: Create one thread and execute a method
608060c859dSBob Moore  *
609060c859dSBob Moore  ******************************************************************************/
610060c859dSBob Moore 
acpi_db_single_execution_thread(void * context)611060c859dSBob Moore static void ACPI_SYSTEM_XFACE acpi_db_single_execution_thread(void *context)
612060c859dSBob Moore {
613060c859dSBob Moore 	struct acpi_db_method_info *info = context;
614060c859dSBob Moore 	acpi_status status;
615060c859dSBob Moore 	struct acpi_buffer return_obj;
616060c859dSBob Moore 
617060c859dSBob Moore 	acpi_os_printf("\n");
618060c859dSBob Moore 
619060c859dSBob Moore 	status = acpi_db_execute_method(info, &return_obj);
620060c859dSBob Moore 	if (ACPI_FAILURE(status)) {
621060c859dSBob Moore 		acpi_os_printf("%s During evaluation of %s\n",
622060c859dSBob Moore 			       acpi_format_exception(status), info->pathname);
623060c859dSBob Moore 		return;
624060c859dSBob Moore 	}
625060c859dSBob Moore 
626060c859dSBob Moore 	/* Display a return object, if any */
627060c859dSBob Moore 
628060c859dSBob Moore 	if (return_obj.length) {
629060c859dSBob Moore 		acpi_os_printf("Evaluation of %s returned object %p, "
630060c859dSBob Moore 			       "external buffer length %X\n",
631060c859dSBob Moore 			       acpi_gbl_db_method_info.pathname,
632060c859dSBob Moore 			       return_obj.pointer, (u32)return_obj.length);
633060c859dSBob Moore 
634060c859dSBob Moore 		acpi_db_dump_external_object(return_obj.pointer, 1);
635060c859dSBob Moore 	}
636060c859dSBob Moore 
637060c859dSBob Moore 	acpi_os_printf("\nBackground thread completed\n%c ",
638060c859dSBob Moore 		       ACPI_DEBUGGER_COMMAND_PROMPT);
639060c859dSBob Moore }
640060c859dSBob Moore 
641060c859dSBob Moore /*******************************************************************************
642060c859dSBob Moore  *
643060c859dSBob Moore  * FUNCTION:    acpi_db_create_execution_thread
644060c859dSBob Moore  *
645060c859dSBob Moore  * PARAMETERS:  method_name_arg         - Control method to execute
646060c859dSBob Moore  *              arguments               - Array of arguments to the method
647060c859dSBob Moore  *              types                   - Corresponding array of object types
648060c859dSBob Moore  *
649060c859dSBob Moore  * RETURN:      None
650060c859dSBob Moore  *
651060c859dSBob Moore  * DESCRIPTION: Create a single thread to evaluate a namespace object. Handles
652060c859dSBob Moore  *              arguments passed on command line for control methods.
653060c859dSBob Moore  *
654060c859dSBob Moore  ******************************************************************************/
655060c859dSBob Moore 
656060c859dSBob Moore void
acpi_db_create_execution_thread(char * method_name_arg,char ** arguments,acpi_object_type * types)657060c859dSBob Moore acpi_db_create_execution_thread(char *method_name_arg,
658060c859dSBob Moore 				char **arguments, acpi_object_type *types)
659060c859dSBob Moore {
660060c859dSBob Moore 	acpi_status status;
661060c859dSBob Moore 	u32 i;
662060c859dSBob Moore 
663060c859dSBob Moore 	memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
664060c859dSBob Moore 	acpi_gbl_db_method_info.name = method_name_arg;
665060c859dSBob Moore 	acpi_gbl_db_method_info.init_args = 1;
666060c859dSBob Moore 	acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments;
667060c859dSBob Moore 	acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types;
668060c859dSBob Moore 
669060c859dSBob Moore 	/* Setup method arguments, up to 7 (0-6) */
670060c859dSBob Moore 
671060c859dSBob Moore 	for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && *arguments; i++) {
672060c859dSBob Moore 		acpi_gbl_db_method_info.arguments[i] = *arguments;
673060c859dSBob Moore 		arguments++;
674060c859dSBob Moore 
675060c859dSBob Moore 		acpi_gbl_db_method_info.arg_types[i] = *types;
676060c859dSBob Moore 		types++;
677060c859dSBob Moore 	}
678060c859dSBob Moore 
679060c859dSBob Moore 	status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
680060c859dSBob Moore 	if (ACPI_FAILURE(status)) {
681060c859dSBob Moore 		return;
682060c859dSBob Moore 	}
683060c859dSBob Moore 
684060c859dSBob Moore 	/* Get the NS node, determines existence also */
685060c859dSBob Moore 
686060c859dSBob Moore 	status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
687060c859dSBob Moore 				 &acpi_gbl_db_method_info.method);
688060c859dSBob Moore 	if (ACPI_FAILURE(status)) {
689060c859dSBob Moore 		acpi_os_printf("%s Could not get handle for %s\n",
690060c859dSBob Moore 			       acpi_format_exception(status),
691060c859dSBob Moore 			       acpi_gbl_db_method_info.pathname);
692060c859dSBob Moore 		return;
693060c859dSBob Moore 	}
694060c859dSBob Moore 
695060c859dSBob Moore 	status = acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD,
696060c859dSBob Moore 				 acpi_db_single_execution_thread,
697060c859dSBob Moore 				 &acpi_gbl_db_method_info);
698060c859dSBob Moore 	if (ACPI_FAILURE(status)) {
699060c859dSBob Moore 		return;
700060c859dSBob Moore 	}
701060c859dSBob Moore 
702060c859dSBob Moore 	acpi_os_printf("\nBackground thread started\n");
703060c859dSBob Moore }
704060c859dSBob Moore 
705060c859dSBob Moore /*******************************************************************************
706060c859dSBob Moore  *
70799575102SLv Zheng  * FUNCTION:    acpi_db_create_execution_threads
70899575102SLv Zheng  *
70999575102SLv Zheng  * PARAMETERS:  num_threads_arg         - Number of threads to create
71099575102SLv Zheng  *              num_loops_arg           - Loop count for the thread(s)
71199575102SLv Zheng  *              method_name_arg         - Control method to execute
71299575102SLv Zheng  *
71399575102SLv Zheng  * RETURN:      None
71499575102SLv Zheng  *
71599575102SLv Zheng  * DESCRIPTION: Create threads to execute method(s)
71699575102SLv Zheng  *
71799575102SLv Zheng  ******************************************************************************/
71899575102SLv Zheng 
71999575102SLv Zheng void
acpi_db_create_execution_threads(char * num_threads_arg,char * num_loops_arg,char * method_name_arg)72099575102SLv Zheng acpi_db_create_execution_threads(char *num_threads_arg,
72199575102SLv Zheng 				 char *num_loops_arg, char *method_name_arg)
72299575102SLv Zheng {
72399575102SLv Zheng 	acpi_status status;
72499575102SLv Zheng 	u32 num_threads;
72599575102SLv Zheng 	u32 num_loops;
72699575102SLv Zheng 	u32 i;
72799575102SLv Zheng 	u32 size;
72899575102SLv Zheng 	acpi_mutex main_thread_gate;
72999575102SLv Zheng 	acpi_mutex thread_complete_gate;
73099575102SLv Zheng 	acpi_mutex info_gate;
73199575102SLv Zheng 
73299575102SLv Zheng 	/* Get the arguments */
73399575102SLv Zheng 
73499575102SLv Zheng 	num_threads = strtoul(num_threads_arg, NULL, 0);
73599575102SLv Zheng 	num_loops = strtoul(num_loops_arg, NULL, 0);
73699575102SLv Zheng 
73799575102SLv Zheng 	if (!num_threads || !num_loops) {
73899575102SLv Zheng 		acpi_os_printf("Bad argument: Threads %X, Loops %X\n",
73999575102SLv Zheng 			       num_threads, num_loops);
74099575102SLv Zheng 		return;
74199575102SLv Zheng 	}
74299575102SLv Zheng 
74399575102SLv Zheng 	/*
74499575102SLv Zheng 	 * Create the semaphore for synchronization of
74599575102SLv Zheng 	 * the created threads with the main thread.
74699575102SLv Zheng 	 */
74799575102SLv Zheng 	status = acpi_os_create_semaphore(1, 0, &main_thread_gate);
74899575102SLv Zheng 	if (ACPI_FAILURE(status)) {
74999575102SLv Zheng 		acpi_os_printf("Could not create semaphore for "
75099575102SLv Zheng 			       "synchronization with the main thread, %s\n",
75199575102SLv Zheng 			       acpi_format_exception(status));
75299575102SLv Zheng 		return;
75399575102SLv Zheng 	}
75499575102SLv Zheng 
75599575102SLv Zheng 	/*
75699575102SLv Zheng 	 * Create the semaphore for synchronization
75799575102SLv Zheng 	 * between the created threads.
75899575102SLv Zheng 	 */
75999575102SLv Zheng 	status = acpi_os_create_semaphore(1, 1, &thread_complete_gate);
76099575102SLv Zheng 	if (ACPI_FAILURE(status)) {
76199575102SLv Zheng 		acpi_os_printf("Could not create semaphore for "
76299575102SLv Zheng 			       "synchronization between the created threads, %s\n",
76399575102SLv Zheng 			       acpi_format_exception(status));
76499575102SLv Zheng 
76599575102SLv Zheng 		(void)acpi_os_delete_semaphore(main_thread_gate);
76699575102SLv Zheng 		return;
76799575102SLv Zheng 	}
76899575102SLv Zheng 
76999575102SLv Zheng 	status = acpi_os_create_semaphore(1, 1, &info_gate);
77099575102SLv Zheng 	if (ACPI_FAILURE(status)) {
77199575102SLv Zheng 		acpi_os_printf("Could not create semaphore for "
77299575102SLv Zheng 			       "synchronization of AcpiGbl_DbMethodInfo, %s\n",
77399575102SLv Zheng 			       acpi_format_exception(status));
77499575102SLv Zheng 
77599575102SLv Zheng 		(void)acpi_os_delete_semaphore(thread_complete_gate);
77699575102SLv Zheng 		(void)acpi_os_delete_semaphore(main_thread_gate);
77799575102SLv Zheng 		return;
77899575102SLv Zheng 	}
77999575102SLv Zheng 
78099575102SLv Zheng 	memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info));
78199575102SLv Zheng 
78299575102SLv Zheng 	/* Array to store IDs of threads */
78399575102SLv Zheng 
78499575102SLv Zheng 	acpi_gbl_db_method_info.num_threads = num_threads;
78599575102SLv Zheng 	size = sizeof(acpi_thread_id) * acpi_gbl_db_method_info.num_threads;
78699575102SLv Zheng 
78799575102SLv Zheng 	acpi_gbl_db_method_info.threads = acpi_os_allocate(size);
78899575102SLv Zheng 	if (acpi_gbl_db_method_info.threads == NULL) {
78999575102SLv Zheng 		acpi_os_printf("No memory for thread IDs array\n");
79099575102SLv Zheng 		(void)acpi_os_delete_semaphore(main_thread_gate);
79199575102SLv Zheng 		(void)acpi_os_delete_semaphore(thread_complete_gate);
79299575102SLv Zheng 		(void)acpi_os_delete_semaphore(info_gate);
79399575102SLv Zheng 		return;
79499575102SLv Zheng 	}
79599575102SLv Zheng 	memset(acpi_gbl_db_method_info.threads, 0, size);
79699575102SLv Zheng 
79799575102SLv Zheng 	/* Setup the context to be passed to each thread */
79899575102SLv Zheng 
79999575102SLv Zheng 	acpi_gbl_db_method_info.name = method_name_arg;
80099575102SLv Zheng 	acpi_gbl_db_method_info.flags = 0;
80199575102SLv Zheng 	acpi_gbl_db_method_info.num_loops = num_loops;
80299575102SLv Zheng 	acpi_gbl_db_method_info.main_thread_gate = main_thread_gate;
80399575102SLv Zheng 	acpi_gbl_db_method_info.thread_complete_gate = thread_complete_gate;
80499575102SLv Zheng 	acpi_gbl_db_method_info.info_gate = info_gate;
80599575102SLv Zheng 
80699575102SLv Zheng 	/* Init arguments to be passed to method */
80799575102SLv Zheng 
80899575102SLv Zheng 	acpi_gbl_db_method_info.init_args = 1;
80999575102SLv Zheng 	acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments;
81099575102SLv Zheng 	acpi_gbl_db_method_info.arguments[0] =
81199575102SLv Zheng 	    acpi_gbl_db_method_info.num_threads_str;
81299575102SLv Zheng 	acpi_gbl_db_method_info.arguments[1] =
81399575102SLv Zheng 	    acpi_gbl_db_method_info.id_of_thread_str;
81499575102SLv Zheng 	acpi_gbl_db_method_info.arguments[2] =
81599575102SLv Zheng 	    acpi_gbl_db_method_info.index_of_thread_str;
81699575102SLv Zheng 	acpi_gbl_db_method_info.arguments[3] = NULL;
81799575102SLv Zheng 
81899575102SLv Zheng 	acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types;
81999575102SLv Zheng 	acpi_gbl_db_method_info.arg_types[0] = ACPI_TYPE_INTEGER;
82099575102SLv Zheng 	acpi_gbl_db_method_info.arg_types[1] = ACPI_TYPE_INTEGER;
82199575102SLv Zheng 	acpi_gbl_db_method_info.arg_types[2] = ACPI_TYPE_INTEGER;
82299575102SLv Zheng 
82399575102SLv Zheng 	acpi_db_uint32_to_hex_string(num_threads,
82499575102SLv Zheng 				     acpi_gbl_db_method_info.num_threads_str);
82599575102SLv Zheng 
82699575102SLv Zheng 	status = acpi_db_execute_setup(&acpi_gbl_db_method_info);
82799575102SLv Zheng 	if (ACPI_FAILURE(status)) {
82899575102SLv Zheng 		goto cleanup_and_exit;
82999575102SLv Zheng 	}
83099575102SLv Zheng 
83199575102SLv Zheng 	/* Get the NS node, determines existence also */
83299575102SLv Zheng 
83399575102SLv Zheng 	status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname,
83499575102SLv Zheng 				 &acpi_gbl_db_method_info.method);
83599575102SLv Zheng 	if (ACPI_FAILURE(status)) {
83699575102SLv Zheng 		acpi_os_printf("%s Could not get handle for %s\n",
83799575102SLv Zheng 			       acpi_format_exception(status),
83899575102SLv Zheng 			       acpi_gbl_db_method_info.pathname);
83999575102SLv Zheng 		goto cleanup_and_exit;
84099575102SLv Zheng 	}
84199575102SLv Zheng 
84299575102SLv Zheng 	/* Create the threads */
84399575102SLv Zheng 
84499575102SLv Zheng 	acpi_os_printf("Creating %X threads to execute %X times each\n",
84599575102SLv Zheng 		       num_threads, num_loops);
84699575102SLv Zheng 
84799575102SLv Zheng 	for (i = 0; i < (num_threads); i++) {
84899575102SLv Zheng 		status =
849f988f24eSLv Zheng 		    acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD,
850f988f24eSLv Zheng 				    acpi_db_method_thread,
85199575102SLv Zheng 				    &acpi_gbl_db_method_info);
85299575102SLv Zheng 		if (ACPI_FAILURE(status)) {
85399575102SLv Zheng 			break;
85499575102SLv Zheng 		}
85599575102SLv Zheng 	}
85699575102SLv Zheng 
85799575102SLv Zheng 	/* Wait for all threads to complete */
85899575102SLv Zheng 
85999575102SLv Zheng 	(void)acpi_os_wait_semaphore(main_thread_gate, 1, ACPI_WAIT_FOREVER);
86099575102SLv Zheng 
86199575102SLv Zheng 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
86299575102SLv Zheng 	acpi_os_printf("All threads (%X) have completed\n", num_threads);
86399575102SLv Zheng 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
86499575102SLv Zheng 
86599575102SLv Zheng cleanup_and_exit:
86699575102SLv Zheng 
86799575102SLv Zheng 	/* Cleanup and exit */
86899575102SLv Zheng 
86999575102SLv Zheng 	(void)acpi_os_delete_semaphore(main_thread_gate);
87099575102SLv Zheng 	(void)acpi_os_delete_semaphore(thread_complete_gate);
87199575102SLv Zheng 	(void)acpi_os_delete_semaphore(info_gate);
87299575102SLv Zheng 
87399575102SLv Zheng 	acpi_os_free(acpi_gbl_db_method_info.threads);
87499575102SLv Zheng 	acpi_gbl_db_method_info.threads = NULL;
87599575102SLv Zheng }
876