/******************************************************************************1*2* Module Name: dsmethod - Parser/Interpreter interface - control method parsing3*4*****************************************************************************/56/*7* Copyright (C) 2000 - 2011, Intel Corp.8* All rights reserved.9*10* Redistribution and use in source and binary forms, with or without11* modification, are permitted provided that the following conditions12* are met:13* 1. Redistributions of source code must retain the above copyright14* notice, this list of conditions, and the following disclaimer,15* without modification.16* 2. Redistributions in binary form must reproduce at minimum a disclaimer17* substantially similar to the "NO WARRANTY" disclaimer below18* ("Disclaimer") and any redistribution must be conditioned upon19* including a substantially similar Disclaimer requirement for further20* binary redistribution.21* 3. Neither the names of the above-listed copyright holders nor the names22* of any contributors may be used to endorse or promote products derived23* from this software without specific prior written permission.24*25* Alternatively, this software may be distributed under the terms of the26* GNU General Public License ("GPL") version 2 as published by the Free27* Software Foundation.28*29* NO WARRANTY30* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS31* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT32* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR33* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT34* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL35* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS36* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)37* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,38* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING39* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE40* POSSIBILITY OF SUCH DAMAGES.41*/4243#include <acpi/acpi.h>44#include "accommon.h"45#include "acdispat.h"46#include "acinterp.h"47#include "acnamesp.h"48#ifdef ACPI_DISASSEMBLER49#include <acpi/acdisasm.h>50#endif5152#define _COMPONENT ACPI_DISPATCHER53ACPI_MODULE_NAME("dsmethod")5455/* Local prototypes */56static acpi_status57acpi_ds_create_method_mutex(union acpi_operand_object *method_desc);5859/*******************************************************************************60*61* FUNCTION: acpi_ds_method_error62*63* PARAMETERS: Status - Execution status64* walk_state - Current state65*66* RETURN: Status67*68* DESCRIPTION: Called on method error. Invoke the global exception handler if69* present, dump the method data if the disassembler is configured70*71* Note: Allows the exception handler to change the status code72*73******************************************************************************/7475acpi_status76acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)77{78ACPI_FUNCTION_ENTRY();7980/* Ignore AE_OK and control exception codes */8182if (ACPI_SUCCESS(status) || (status & AE_CODE_CONTROL)) {83return (status);84}8586/* Invoke the global exception handler */8788if (acpi_gbl_exception_handler) {8990/* Exit the interpreter, allow handler to execute methods */9192acpi_ex_exit_interpreter();9394/*95* Handler can map the exception code to anything it wants, including96* AE_OK, in which case the executing method will not be aborted.97*/98status = acpi_gbl_exception_handler(status,99walk_state->method_node ?100walk_state->method_node->101name.integer : 0,102walk_state->opcode,103walk_state->aml_offset,104NULL);105acpi_ex_enter_interpreter();106}107108acpi_ds_clear_implicit_return(walk_state);109110#ifdef ACPI_DISASSEMBLER111if (ACPI_FAILURE(status)) {112113/* Display method locals/args if disassembler is present */114115acpi_dm_dump_method_info(status, walk_state, walk_state->op);116}117#endif118119return (status);120}121122/*******************************************************************************123*124* FUNCTION: acpi_ds_create_method_mutex125*126* PARAMETERS: obj_desc - The method object127*128* RETURN: Status129*130* DESCRIPTION: Create a mutex object for a serialized control method131*132******************************************************************************/133134static acpi_status135acpi_ds_create_method_mutex(union acpi_operand_object *method_desc)136{137union acpi_operand_object *mutex_desc;138acpi_status status;139140ACPI_FUNCTION_TRACE(ds_create_method_mutex);141142/* Create the new mutex object */143144mutex_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX);145if (!mutex_desc) {146return_ACPI_STATUS(AE_NO_MEMORY);147}148149/* Create the actual OS Mutex */150151status = acpi_os_create_mutex(&mutex_desc->mutex.os_mutex);152if (ACPI_FAILURE(status)) {153return_ACPI_STATUS(status);154}155156mutex_desc->mutex.sync_level = method_desc->method.sync_level;157method_desc->method.mutex = mutex_desc;158return_ACPI_STATUS(AE_OK);159}160161/*******************************************************************************162*163* FUNCTION: acpi_ds_begin_method_execution164*165* PARAMETERS: method_node - Node of the method166* obj_desc - The method object167* walk_state - current state, NULL if not yet executing168* a method.169*170* RETURN: Status171*172* DESCRIPTION: Prepare a method for execution. Parses the method if necessary,173* increments the thread count, and waits at the method semaphore174* for clearance to execute.175*176******************************************************************************/177178acpi_status179acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,180union acpi_operand_object *obj_desc,181struct acpi_walk_state *walk_state)182{183acpi_status status = AE_OK;184185ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node);186187if (!method_node) {188return_ACPI_STATUS(AE_NULL_ENTRY);189}190191/* Prevent wraparound of thread count */192193if (obj_desc->method.thread_count == ACPI_UINT8_MAX) {194ACPI_ERROR((AE_INFO,195"Method reached maximum reentrancy limit (255)"));196return_ACPI_STATUS(AE_AML_METHOD_LIMIT);197}198199/*200* If this method is serialized, we need to acquire the method mutex.201*/202if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) {203/*204* Create a mutex for the method if it is defined to be Serialized205* and a mutex has not already been created. We defer the mutex creation206* until a method is actually executed, to minimize the object count207*/208if (!obj_desc->method.mutex) {209status = acpi_ds_create_method_mutex(obj_desc);210if (ACPI_FAILURE(status)) {211return_ACPI_STATUS(status);212}213}214215/*216* The current_sync_level (per-thread) must be less than or equal to217* the sync level of the method. This mechanism provides some218* deadlock prevention219*220* Top-level method invocation has no walk state at this point221*/222if (walk_state &&223(walk_state->thread->current_sync_level >224obj_desc->method.mutex->mutex.sync_level)) {225ACPI_ERROR((AE_INFO,226"Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)",227acpi_ut_get_node_name(method_node),228walk_state->thread->current_sync_level));229230return_ACPI_STATUS(AE_AML_MUTEX_ORDER);231}232233/*234* Obtain the method mutex if necessary. Do not acquire mutex for a235* recursive call.236*/237if (!walk_state ||238!obj_desc->method.mutex->mutex.thread_id ||239(walk_state->thread->thread_id !=240obj_desc->method.mutex->mutex.thread_id)) {241/*242* Acquire the method mutex. This releases the interpreter if we243* block (and reacquires it before it returns)244*/245status =246acpi_ex_system_wait_mutex(obj_desc->method.mutex->247mutex.os_mutex,248ACPI_WAIT_FOREVER);249if (ACPI_FAILURE(status)) {250return_ACPI_STATUS(status);251}252253/* Update the mutex and walk info and save the original sync_level */254255if (walk_state) {256obj_desc->method.mutex->mutex.257original_sync_level =258walk_state->thread->current_sync_level;259260obj_desc->method.mutex->mutex.thread_id =261walk_state->thread->thread_id;262walk_state->thread->current_sync_level =263obj_desc->method.sync_level;264} else {265obj_desc->method.mutex->mutex.266original_sync_level =267obj_desc->method.mutex->mutex.sync_level;268}269}270271/* Always increase acquisition depth */272273obj_desc->method.mutex->mutex.acquisition_depth++;274}275276/*277* Allocate an Owner ID for this method, only if this is the first thread278* to begin concurrent execution. We only need one owner_id, even if the279* method is invoked recursively.280*/281if (!obj_desc->method.owner_id) {282status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);283if (ACPI_FAILURE(status)) {284goto cleanup;285}286}287288/*289* Increment the method parse tree thread count since it has been290* reentered one more time (even if it is the same thread)291*/292obj_desc->method.thread_count++;293return_ACPI_STATUS(status);294295cleanup:296/* On error, must release the method mutex (if present) */297298if (obj_desc->method.mutex) {299acpi_os_release_mutex(obj_desc->method.mutex->mutex.os_mutex);300}301return_ACPI_STATUS(status);302}303304/*******************************************************************************305*306* FUNCTION: acpi_ds_call_control_method307*308* PARAMETERS: Thread - Info for this thread309* this_walk_state - Current walk state310* Op - Current Op to be walked311*312* RETURN: Status313*314* DESCRIPTION: Transfer execution to a called control method315*316******************************************************************************/317318acpi_status319acpi_ds_call_control_method(struct acpi_thread_state *thread,320struct acpi_walk_state *this_walk_state,321union acpi_parse_object *op)322{323acpi_status status;324struct acpi_namespace_node *method_node;325struct acpi_walk_state *next_walk_state = NULL;326union acpi_operand_object *obj_desc;327struct acpi_evaluate_info *info;328u32 i;329330ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state);331332ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,333"Calling method %p, currentstate=%p\n",334this_walk_state->prev_op, this_walk_state));335336/*337* Get the namespace entry for the control method we are about to call338*/339method_node = this_walk_state->method_call_node;340if (!method_node) {341return_ACPI_STATUS(AE_NULL_ENTRY);342}343344obj_desc = acpi_ns_get_attached_object(method_node);345if (!obj_desc) {346return_ACPI_STATUS(AE_NULL_OBJECT);347}348349/* Init for new method, possibly wait on method mutex */350351status = acpi_ds_begin_method_execution(method_node, obj_desc,352this_walk_state);353if (ACPI_FAILURE(status)) {354return_ACPI_STATUS(status);355}356357/* Begin method parse/execution. Create a new walk state */358359next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,360NULL, obj_desc, thread);361if (!next_walk_state) {362status = AE_NO_MEMORY;363goto cleanup;364}365366/*367* The resolved arguments were put on the previous walk state's operand368* stack. Operands on the previous walk state stack always369* start at index 0. Also, null terminate the list of arguments370*/371this_walk_state->operands[this_walk_state->num_operands] = NULL;372373/*374* Allocate and initialize the evaluation information block375* TBD: this is somewhat inefficient, should change interface to376* ds_init_aml_walk. For now, keeps this struct off the CPU stack377*/378info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));379if (!info) {380return_ACPI_STATUS(AE_NO_MEMORY);381}382383info->parameters = &this_walk_state->operands[0];384385status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,386obj_desc->method.aml_start,387obj_desc->method.aml_length, info,388ACPI_IMODE_EXECUTE);389390ACPI_FREE(info);391if (ACPI_FAILURE(status)) {392goto cleanup;393}394395/*396* Delete the operands on the previous walkstate operand stack397* (they were copied to new objects)398*/399for (i = 0; i < obj_desc->method.param_count; i++) {400acpi_ut_remove_reference(this_walk_state->operands[i]);401this_walk_state->operands[i] = NULL;402}403404/* Clear the operand stack */405406this_walk_state->num_operands = 0;407408ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,409"**** Begin nested execution of [%4.4s] **** WalkState=%p\n",410method_node->name.ascii, next_walk_state));411412/* Invoke an internal method if necessary */413414if (obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {415status =416obj_desc->method.dispatch.implementation(next_walk_state);417if (status == AE_OK) {418status = AE_CTRL_TERMINATE;419}420}421422return_ACPI_STATUS(status);423424cleanup:425426/* On error, we must terminate the method properly */427428acpi_ds_terminate_control_method(obj_desc, next_walk_state);429if (next_walk_state) {430acpi_ds_delete_walk_state(next_walk_state);431}432433return_ACPI_STATUS(status);434}435436/*******************************************************************************437*438* FUNCTION: acpi_ds_restart_control_method439*440* PARAMETERS: walk_state - State for preempted method (caller)441* return_desc - Return value from the called method442*443* RETURN: Status444*445* DESCRIPTION: Restart a method that was preempted by another (nested) method446* invocation. Handle the return value (if any) from the callee.447*448******************************************************************************/449450acpi_status451acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,452union acpi_operand_object *return_desc)453{454acpi_status status;455int same_as_implicit_return;456457ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state);458459ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,460"****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",461acpi_ut_get_node_name(walk_state->method_node),462walk_state->method_call_op, return_desc));463464ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,465" ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",466walk_state->return_used,467walk_state->results, walk_state));468469/* Did the called method return a value? */470471if (return_desc) {472473/* Is the implicit return object the same as the return desc? */474475same_as_implicit_return =476(walk_state->implicit_return_obj == return_desc);477478/* Are we actually going to use the return value? */479480if (walk_state->return_used) {481482/* Save the return value from the previous method */483484status = acpi_ds_result_push(return_desc, walk_state);485if (ACPI_FAILURE(status)) {486acpi_ut_remove_reference(return_desc);487return_ACPI_STATUS(status);488}489490/*491* Save as THIS method's return value in case it is returned492* immediately to yet another method493*/494walk_state->return_desc = return_desc;495}496497/*498* The following code is the optional support for the so-called499* "implicit return". Some AML code assumes that the last value of the500* method is "implicitly" returned to the caller, in the absence of an501* explicit return value.502*503* Just save the last result of the method as the return value.504*505* NOTE: this is optional because the ASL language does not actually506* support this behavior.507*/508else if (!acpi_ds_do_implicit_return509(return_desc, walk_state, FALSE)510|| same_as_implicit_return) {511/*512* Delete the return value if it will not be used by the513* calling method or remove one reference if the explicit return514* is the same as the implicit return value.515*/516acpi_ut_remove_reference(return_desc);517}518}519520return_ACPI_STATUS(AE_OK);521}522523/*******************************************************************************524*525* FUNCTION: acpi_ds_terminate_control_method526*527* PARAMETERS: method_desc - Method object528* walk_state - State associated with the method529*530* RETURN: None531*532* DESCRIPTION: Terminate a control method. Delete everything that the method533* created, delete all locals and arguments, and delete the parse534* tree if requested.535*536* MUTEX: Interpreter is locked537*538******************************************************************************/539540void541acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,542struct acpi_walk_state *walk_state)543{544545ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state);546547/* method_desc is required, walk_state is optional */548549if (!method_desc) {550return_VOID;551}552553if (walk_state) {554555/* Delete all arguments and locals */556557acpi_ds_method_data_delete_all(walk_state);558559/*560* If method is serialized, release the mutex and restore the561* current sync level for this thread562*/563if (method_desc->method.mutex) {564565/* Acquisition Depth handles recursive calls */566567method_desc->method.mutex->mutex.acquisition_depth--;568if (!method_desc->method.mutex->mutex.acquisition_depth) {569walk_state->thread->current_sync_level =570method_desc->method.mutex->mutex.571original_sync_level;572573acpi_os_release_mutex(method_desc->method.574mutex->mutex.os_mutex);575method_desc->method.mutex->mutex.thread_id = 0;576}577}578579/*580* Delete any namespace objects created anywhere within the581* namespace by the execution of this method. Unless:582* 1) This method is a module-level executable code method, in which583* case we want make the objects permanent.584* 2) There are other threads executing the method, in which case we585* will wait until the last thread has completed.586*/587if (!(method_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL)588&& (method_desc->method.thread_count == 1)) {589590/* Delete any direct children of (created by) this method */591592acpi_ns_delete_namespace_subtree(walk_state->593method_node);594595/*596* Delete any objects that were created by this method597* elsewhere in the namespace (if any were created).598* Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the599* deletion such that we don't have to perform an entire600* namespace walk for every control method execution.601*/602if (method_desc->method.603info_flags & ACPI_METHOD_MODIFIED_NAMESPACE) {604acpi_ns_delete_namespace_by_owner(method_desc->605method.606owner_id);607method_desc->method.info_flags &=608~ACPI_METHOD_MODIFIED_NAMESPACE;609}610}611}612613/* Decrement the thread count on the method */614615if (method_desc->method.thread_count) {616method_desc->method.thread_count--;617} else {618ACPI_ERROR((AE_INFO, "Invalid zero thread count in method"));619}620621/* Are there any other threads currently executing this method? */622623if (method_desc->method.thread_count) {624/*625* Additional threads. Do not release the owner_id in this case,626* we immediately reuse it for the next thread executing this method627*/628ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,629"*** Completed execution of one thread, %u threads remaining\n",630method_desc->method.thread_count));631} else {632/* This is the only executing thread for this method */633634/*635* Support to dynamically change a method from not_serialized to636* Serialized if it appears that the method is incorrectly written and637* does not support multiple thread execution. The best example of this638* is if such a method creates namespace objects and blocks. A second639* thread will fail with an AE_ALREADY_EXISTS exception.640*641* This code is here because we must wait until the last thread exits642* before marking the method as serialized.643*/644if (method_desc->method.645info_flags & ACPI_METHOD_SERIALIZED_PENDING) {646if (walk_state) {647ACPI_INFO((AE_INFO,648"Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",649walk_state->method_node->name.650ascii));651}652653/*654* Method tried to create an object twice and was marked as655* "pending serialized". The probable cause is that the method656* cannot handle reentrancy.657*658* The method was created as not_serialized, but it tried to create659* a named object and then blocked, causing the second thread660* entrance to begin and then fail. Workaround this problem by661* marking the method permanently as Serialized when the last662* thread exits here.663*/664method_desc->method.info_flags &=665~ACPI_METHOD_SERIALIZED_PENDING;666method_desc->method.info_flags |=667ACPI_METHOD_SERIALIZED;668method_desc->method.sync_level = 0;669}670671/* No more threads, we can free the owner_id */672673if (!674(method_desc->method.675info_flags & ACPI_METHOD_MODULE_LEVEL)) {676acpi_ut_release_owner_id(&method_desc->method.owner_id);677}678}679680return_VOID;681}682683684