167754Smsmith/******************************************************************************* 267754Smsmith * 367754Smsmith * Module Name: dbexec - debugger control method execution 467754Smsmith * 567754Smsmith ******************************************************************************/ 667754Smsmith 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 970243Smsmith * All rights reserved. 1067754Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2567754Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2967754Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4367754Smsmith 4467754Smsmith 45193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 46193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 47193341Sjkim#include <contrib/dev/acpica/include/acdebug.h> 48193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 4967754Smsmith 50102550Siwasaki#ifdef ACPI_DEBUGGER 5167754Smsmith 52102550Siwasaki#define _COMPONENT ACPI_CA_DEBUGGER 5391116Smsmith ACPI_MODULE_NAME ("dbexec") 5467754Smsmith 5567754Smsmith 56222544Sjkimstatic ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo; 5767754Smsmith 58151937Sjkim/* Local prototypes */ 5967754Smsmith 60151937Sjkimstatic ACPI_STATUS 61151937SjkimAcpiDbExecuteMethod ( 62151937Sjkim ACPI_DB_METHOD_INFO *Info, 63151937Sjkim ACPI_BUFFER *ReturnObj); 64151937Sjkim 65151937Sjkimstatic void 66151937SjkimAcpiDbExecuteSetup ( 67151937Sjkim ACPI_DB_METHOD_INFO *Info); 68151937Sjkim 69151937Sjkimstatic UINT32 70151937SjkimAcpiDbGetOutstandingAllocations ( 71151937Sjkim void); 72151937Sjkim 73151937Sjkimstatic void ACPI_SYSTEM_XFACE 74151937SjkimAcpiDbMethodThread ( 75151937Sjkim void *Context); 76151937Sjkim 77151937Sjkimstatic ACPI_STATUS 78151937SjkimAcpiDbExecutionWalk ( 79151937Sjkim ACPI_HANDLE ObjHandle, 80151937Sjkim UINT32 NestingLevel, 81151937Sjkim void *Context, 82151937Sjkim void **ReturnValue); 83151937Sjkim 84151937Sjkim 8567754Smsmith/******************************************************************************* 8667754Smsmith * 87222544Sjkim * FUNCTION: AcpiDbDeleteObjects 88222544Sjkim * 89222544Sjkim * PARAMETERS: Count - Count of objects in the list 90222544Sjkim * Objects - Array of ACPI_OBJECTs to be deleted 91222544Sjkim * 92222544Sjkim * RETURN: None 93222544Sjkim * 94222544Sjkim * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested 95222544Sjkim * packages via recursion. 96222544Sjkim * 97222544Sjkim ******************************************************************************/ 98222544Sjkim 99245582Sjkimvoid 100222544SjkimAcpiDbDeleteObjects ( 101222544Sjkim UINT32 Count, 102222544Sjkim ACPI_OBJECT *Objects) 103222544Sjkim{ 104222544Sjkim UINT32 i; 105222544Sjkim 106222544Sjkim 107222544Sjkim for (i = 0; i < Count; i++) 108222544Sjkim { 109222544Sjkim switch (Objects[i].Type) 110222544Sjkim { 111222544Sjkim case ACPI_TYPE_BUFFER: 112250838Sjkim 113222544Sjkim ACPI_FREE (Objects[i].Buffer.Pointer); 114222544Sjkim break; 115222544Sjkim 116222544Sjkim case ACPI_TYPE_PACKAGE: 117222544Sjkim 118222544Sjkim /* Recursive call to delete package elements */ 119222544Sjkim 120222544Sjkim AcpiDbDeleteObjects (Objects[i].Package.Count, 121222544Sjkim Objects[i].Package.Elements); 122222544Sjkim 123222544Sjkim /* Free the elements array */ 124222544Sjkim 125222544Sjkim ACPI_FREE (Objects[i].Package.Elements); 126222544Sjkim break; 127222544Sjkim 128222544Sjkim default: 129250838Sjkim 130222544Sjkim break; 131222544Sjkim } 132222544Sjkim } 133222544Sjkim} 134222544Sjkim 135222544Sjkim 136222544Sjkim/******************************************************************************* 137222544Sjkim * 13867754Smsmith * FUNCTION: AcpiDbExecuteMethod 13967754Smsmith * 14067754Smsmith * PARAMETERS: Info - Valid info segment 14167754Smsmith * ReturnObj - Where to put return object 14267754Smsmith * 14367754Smsmith * RETURN: Status 14467754Smsmith * 14567754Smsmith * DESCRIPTION: Execute a control method. 14667754Smsmith * 14767754Smsmith ******************************************************************************/ 14867754Smsmith 149151937Sjkimstatic ACPI_STATUS 15067754SmsmithAcpiDbExecuteMethod ( 15191116Smsmith ACPI_DB_METHOD_INFO *Info, 15267754Smsmith ACPI_BUFFER *ReturnObj) 15367754Smsmith{ 15467754Smsmith ACPI_STATUS Status; 15567754Smsmith ACPI_OBJECT_LIST ParamObjects; 156249663Sjkim ACPI_OBJECT Params[ACPI_DEBUGGER_MAX_ARGS + 1]; 15767754Smsmith UINT32 i; 15867754Smsmith 15967754Smsmith 160216471Sjkim ACPI_FUNCTION_TRACE (DbExecuteMethod); 161216471Sjkim 162216471Sjkim 16383174Smsmith if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel) 16467754Smsmith { 16567754Smsmith AcpiOsPrintf ("Warning: debug output is not enabled!\n"); 16667754Smsmith } 16767754Smsmith 168249663Sjkim ParamObjects.Count = 0; 169249663Sjkim ParamObjects.Pointer = NULL; 170193267Sjkim 171249663Sjkim /* Pass through any command-line arguments */ 172193267Sjkim 173249663Sjkim if (Info->Args && Info->Args[0]) 17467754Smsmith { 175249663Sjkim /* Get arguments passed on the command line */ 17667754Smsmith 177249663Sjkim for (i = 0; (Info->Args[i] && *(Info->Args[i])); i++) 178193267Sjkim { 179249663Sjkim /* Convert input string (token) to an actual ACPI_OBJECT */ 180222544Sjkim 181249663Sjkim Status = AcpiDbConvertToObject (Info->Types[i], 182249663Sjkim Info->Args[i], &Params[i]); 183249663Sjkim if (ACPI_FAILURE (Status)) 184193267Sjkim { 185249663Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 186249663Sjkim "While parsing method arguments")); 187249663Sjkim goto Cleanup; 188193267Sjkim } 189222544Sjkim } 19067754Smsmith 191249663Sjkim ParamObjects.Count = i; 192222544Sjkim ParamObjects.Pointer = Params; 19367754Smsmith } 19467754Smsmith 19567754Smsmith /* Prepare for a return object of arbitrary size */ 19667754Smsmith 197151937Sjkim ReturnObj->Pointer = AcpiGbl_DbBuffer; 198151937Sjkim ReturnObj->Length = ACPI_DEBUG_BUFFER_SIZE; 19967754Smsmith 20067754Smsmith /* Do the actual method execution */ 20167754Smsmith 202114237Snjl AcpiGbl_MethodExecuting = TRUE; 203249663Sjkim Status = AcpiEvaluateObject (NULL, Info->Pathname, 204249663Sjkim &ParamObjects, ReturnObj); 20567754Smsmith 20667754Smsmith AcpiGbl_CmSingleStep = FALSE; 20767754Smsmith AcpiGbl_MethodExecuting = FALSE; 20867754Smsmith 209216471Sjkim if (ACPI_FAILURE (Status)) 210216471Sjkim { 211216471Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 212222544Sjkim "while executing %s from debugger", Info->Pathname)); 213216471Sjkim 214216471Sjkim if (Status == AE_BUFFER_OVERFLOW) 215216471Sjkim { 216216471Sjkim ACPI_ERROR ((AE_INFO, 217222544Sjkim "Possible overflow of internal debugger buffer (size 0x%X needed 0x%X)", 218216471Sjkim ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length)); 219216471Sjkim } 220216471Sjkim } 221216471Sjkim 222222544SjkimCleanup: 223249663Sjkim AcpiDbDeleteObjects (ParamObjects.Count, Params); 224216471Sjkim return_ACPI_STATUS (Status); 22567754Smsmith} 22667754Smsmith 22767754Smsmith 22867754Smsmith/******************************************************************************* 22967754Smsmith * 23067754Smsmith * FUNCTION: AcpiDbExecuteSetup 23167754Smsmith * 23267754Smsmith * PARAMETERS: Info - Valid method info 23367754Smsmith * 234151937Sjkim * RETURN: None 23567754Smsmith * 23667754Smsmith * DESCRIPTION: Setup info segment prior to method execution 23767754Smsmith * 23867754Smsmith ******************************************************************************/ 23967754Smsmith 240151937Sjkimstatic void 24167754SmsmithAcpiDbExecuteSetup ( 24299679Siwasaki ACPI_DB_METHOD_INFO *Info) 24367754Smsmith{ 24467754Smsmith 24567754Smsmith /* Catenate the current scope to the supplied name */ 24667754Smsmith 24767754Smsmith Info->Pathname[0] = 0; 24867754Smsmith if ((Info->Name[0] != '\\') && 24967754Smsmith (Info->Name[0] != '/')) 25067754Smsmith { 25191116Smsmith ACPI_STRCAT (Info->Pathname, AcpiGbl_DbScopeBuf); 25267754Smsmith } 25367754Smsmith 25491116Smsmith ACPI_STRCAT (Info->Pathname, Info->Name); 25567754Smsmith AcpiDbPrepNamestring (Info->Pathname); 25667754Smsmith 25791116Smsmith AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 258240716Sjkim AcpiOsPrintf ("Evaluating %s\n", Info->Pathname); 25967754Smsmith 26067754Smsmith if (Info->Flags & EX_SINGLE_STEP) 26167754Smsmith { 26267754Smsmith AcpiGbl_CmSingleStep = TRUE; 26391116Smsmith AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 26467754Smsmith } 26567754Smsmith 26667754Smsmith else 26767754Smsmith { 26867754Smsmith /* No single step, allow redirection to a file */ 26967754Smsmith 27091116Smsmith AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 27167754Smsmith } 27267754Smsmith} 27367754Smsmith 27467754Smsmith 275151937Sjkim#ifdef ACPI_DBG_TRACK_ALLOCATIONS 276167802SjkimUINT32 277151937SjkimAcpiDbGetCacheInfo ( 278151937Sjkim ACPI_MEMORY_LIST *Cache) 279151937Sjkim{ 280151937Sjkim 281151937Sjkim return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth); 282151937Sjkim} 283151937Sjkim#endif 284151937Sjkim 28567754Smsmith/******************************************************************************* 28667754Smsmith * 28782367Smsmith * FUNCTION: AcpiDbGetOutstandingAllocations 28882367Smsmith * 28982367Smsmith * PARAMETERS: None 29082367Smsmith * 29182367Smsmith * RETURN: Current global allocation count minus cache entries 29282367Smsmith * 29382367Smsmith * DESCRIPTION: Determine the current number of "outstanding" allocations -- 29482367Smsmith * those allocations that have not been freed and also are not 29582367Smsmith * in one of the various object caches. 29682367Smsmith * 29782367Smsmith ******************************************************************************/ 29882367Smsmith 299151937Sjkimstatic UINT32 30099679SiwasakiAcpiDbGetOutstandingAllocations ( 30199679Siwasaki void) 30282367Smsmith{ 30382367Smsmith UINT32 Outstanding = 0; 30482367Smsmith 30582367Smsmith#ifdef ACPI_DBG_TRACK_ALLOCATIONS 30682367Smsmith 307151937Sjkim Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache); 308151937Sjkim Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache); 309151937Sjkim Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache); 310151937Sjkim Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache); 31182367Smsmith#endif 31282367Smsmith 31382367Smsmith return (Outstanding); 31482367Smsmith} 31582367Smsmith 31682367Smsmith 31782367Smsmith/******************************************************************************* 31882367Smsmith * 319114237Snjl * FUNCTION: AcpiDbExecutionWalk 320114237Snjl * 321114237Snjl * PARAMETERS: WALK_CALLBACK 322114237Snjl * 323114237Snjl * RETURN: Status 324114237Snjl * 325241973Sjkim * DESCRIPTION: Execute a control method. Name is relative to the current 326114237Snjl * scope. 327114237Snjl * 328114237Snjl ******************************************************************************/ 329114237Snjl 330151937Sjkimstatic ACPI_STATUS 331114237SnjlAcpiDbExecutionWalk ( 332114237Snjl ACPI_HANDLE ObjHandle, 333114237Snjl UINT32 NestingLevel, 334114237Snjl void *Context, 335114237Snjl void **ReturnValue) 336114237Snjl{ 337114237Snjl ACPI_OPERAND_OBJECT *ObjDesc; 338114237Snjl ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 339114237Snjl ACPI_BUFFER ReturnObj; 340114237Snjl ACPI_STATUS Status; 341114237Snjl 342114237Snjl 343114237Snjl ObjDesc = AcpiNsGetAttachedObject (Node); 344114237Snjl if (ObjDesc->Method.ParamCount) 345114237Snjl { 346114237Snjl return (AE_OK); 347114237Snjl } 348114237Snjl 349114237Snjl ReturnObj.Pointer = NULL; 350114237Snjl ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 351114237Snjl 352240716Sjkim AcpiNsPrintNodePathname (Node, "Evaluating"); 353114237Snjl 354114237Snjl /* Do the actual method execution */ 355114237Snjl 356114237Snjl AcpiOsPrintf ("\n"); 357114237Snjl AcpiGbl_MethodExecuting = TRUE; 358114237Snjl 359114237Snjl Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj); 360114237Snjl 361240716Sjkim AcpiOsPrintf ("Evaluation of [%4.4s] returned %s\n", AcpiUtGetNodeName (Node), 362123315Snjl AcpiFormatException (Status)); 363114237Snjl AcpiGbl_MethodExecuting = FALSE; 364114237Snjl 365114237Snjl return (AE_OK); 366114237Snjl} 367114237Snjl 368114237Snjl 369114237Snjl/******************************************************************************* 370114237Snjl * 37167754Smsmith * FUNCTION: AcpiDbExecute 37267754Smsmith * 37367754Smsmith * PARAMETERS: Name - Name of method to execute 37467754Smsmith * Args - Parameters to the method 37567754Smsmith * Flags - single step/no single step 37667754Smsmith * 377151937Sjkim * RETURN: None 37867754Smsmith * 379241973Sjkim * DESCRIPTION: Execute a control method. Name is relative to the current 38067754Smsmith * scope. 38167754Smsmith * 38267754Smsmith ******************************************************************************/ 38367754Smsmith 38467754Smsmithvoid 38567754SmsmithAcpiDbExecute ( 386114237Snjl char *Name, 387114237Snjl char **Args, 388222544Sjkim ACPI_OBJECT_TYPE *Types, 38967754Smsmith UINT32 Flags) 39067754Smsmith{ 39167754Smsmith ACPI_STATUS Status; 39269450Smsmith ACPI_BUFFER ReturnObj; 393167802Sjkim char *NameString; 39469450Smsmith 39569450Smsmith 396102550Siwasaki#ifdef ACPI_DEBUG_OUTPUT 39767754Smsmith UINT32 PreviousAllocations; 39867754Smsmith UINT32 Allocations; 39967754Smsmith 40067754Smsmith 40167754Smsmith /* Memory allocation tracking */ 40267754Smsmith 40382367Smsmith PreviousAllocations = AcpiDbGetOutstandingAllocations (); 40469450Smsmith#endif 40567754Smsmith 406114237Snjl if (*Name == '*') 407114237Snjl { 408151937Sjkim (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, 409199337Sjkim ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL); 410114237Snjl return; 411114237Snjl } 412114237Snjl else 413114237Snjl { 414167802Sjkim NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1); 415167802Sjkim if (!NameString) 416167802Sjkim { 417167802Sjkim return; 418167802Sjkim } 419167802Sjkim 420167802Sjkim ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 421167802Sjkim 422167802Sjkim ACPI_STRCPY (NameString, Name); 423167802Sjkim AcpiUtStrupr (NameString); 424167802Sjkim AcpiGbl_DbMethodInfo.Name = NameString; 425114237Snjl AcpiGbl_DbMethodInfo.Args = Args; 426222544Sjkim AcpiGbl_DbMethodInfo.Types = Types; 427114237Snjl AcpiGbl_DbMethodInfo.Flags = Flags; 42867754Smsmith 429114237Snjl ReturnObj.Pointer = NULL; 430114237Snjl ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 431100966Siwasaki 432114237Snjl AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 433239340Sjkim 434239340Sjkim /* Get the NS node, determines existence also */ 435239340Sjkim 436239340Sjkim Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 437239340Sjkim &AcpiGbl_DbMethodInfo.Method); 438245582Sjkim if (ACPI_SUCCESS (Status)) 439239340Sjkim { 440245582Sjkim Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj); 441239340Sjkim } 442167802Sjkim ACPI_FREE (NameString); 443114237Snjl } 44467754Smsmith 44582367Smsmith /* 44682367Smsmith * Allow any handlers in separate threads to complete. 44782367Smsmith * (Such as Notify handlers invoked from AML executed above). 44882367Smsmith */ 449202771Sjkim AcpiOsSleep ((UINT64) 10); 45067754Smsmith 451102550Siwasaki#ifdef ACPI_DEBUG_OUTPUT 45269450Smsmith 45367754Smsmith /* Memory allocation tracking */ 45467754Smsmith 45582367Smsmith Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations; 45667754Smsmith 45791116Smsmith AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 45867754Smsmith 45967754Smsmith if (Allocations > 0) 46067754Smsmith { 461240716Sjkim AcpiOsPrintf ("0x%X Outstanding allocations after evaluation of %s\n", 462240716Sjkim Allocations, AcpiGbl_DbMethodInfo.Pathname); 46367754Smsmith } 46469450Smsmith#endif 46567754Smsmith 46667754Smsmith if (ACPI_FAILURE (Status)) 46767754Smsmith { 468240716Sjkim AcpiOsPrintf ("Evaluation of %s failed with status %s\n", 46983174Smsmith AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status)); 47067754Smsmith } 47167754Smsmith else 47267754Smsmith { 47367754Smsmith /* Display a return object, if any */ 47467754Smsmith 47567754Smsmith if (ReturnObj.Length) 47667754Smsmith { 477240716Sjkim AcpiOsPrintf ( 478240716Sjkim "Evaluation of %s returned object %p, external buffer length %X\n", 479114237Snjl AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer, 480104470Siwasaki (UINT32) ReturnObj.Length); 481151937Sjkim AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 482239340Sjkim 483239340Sjkim /* Dump a _PLD buffer if present */ 484239340Sjkim 485239340Sjkim if (ACPI_COMPARE_NAME ((ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, 486239340Sjkim AcpiGbl_DbMethodInfo.Method)->Name.Ascii), METHOD_NAME__PLD)) 487239340Sjkim { 488239340Sjkim AcpiDbDumpPldBuffer (ReturnObj.Pointer); 489239340Sjkim } 49067754Smsmith } 491100966Siwasaki else 492100966Siwasaki { 493240716Sjkim AcpiOsPrintf ("No object was returned from evaluation of %s\n", 494100966Siwasaki AcpiGbl_DbMethodInfo.Pathname); 495100966Siwasaki } 49667754Smsmith } 49767754Smsmith 49891116Smsmith AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 49967754Smsmith} 50067754Smsmith 50167754Smsmith 50267754Smsmith/******************************************************************************* 50367754Smsmith * 50467754Smsmith * FUNCTION: AcpiDbMethodThread 50567754Smsmith * 50667754Smsmith * PARAMETERS: Context - Execution info segment 50767754Smsmith * 50867754Smsmith * RETURN: None 50967754Smsmith * 510241973Sjkim * DESCRIPTION: Debugger execute thread. Waits for a command line, then 51167754Smsmith * simply dispatches it. 51267754Smsmith * 51367754Smsmith ******************************************************************************/ 51467754Smsmith 515151937Sjkimstatic void ACPI_SYSTEM_XFACE 51667754SmsmithAcpiDbMethodThread ( 51767754Smsmith void *Context) 51867754Smsmith{ 51967754Smsmith ACPI_STATUS Status; 52091116Smsmith ACPI_DB_METHOD_INFO *Info = Context; 521193267Sjkim ACPI_DB_METHOD_INFO LocalInfo; 52267754Smsmith UINT32 i; 523167802Sjkim UINT8 Allow; 52467754Smsmith ACPI_BUFFER ReturnObj; 52567754Smsmith 52667754Smsmith 527193267Sjkim /* 528193267Sjkim * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments. 529193267Sjkim * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads 530193267Sjkim * concurrently. 531193267Sjkim * 532193267Sjkim * Note: The arguments we are passing are used by the ASL test suite 533193267Sjkim * (aslts). Do not change them without updating the tests. 534193267Sjkim */ 535193267Sjkim (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER); 536193267Sjkim 537167802Sjkim if (Info->InitArgs) 538167802Sjkim { 539237412Sjkim AcpiDbUint32ToHexString (Info->NumCreated, Info->IndexOfThreadStr); 540237412Sjkim AcpiDbUint32ToHexString ((UINT32) AcpiOsGetThreadId (), Info->IdOfThreadStr); 541167802Sjkim } 542167802Sjkim 543167802Sjkim if (Info->Threads && (Info->NumCreated < Info->NumThreads)) 544167802Sjkim { 545212761Sjkim Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId(); 546167802Sjkim } 547167802Sjkim 548193267Sjkim LocalInfo = *Info; 549193267Sjkim LocalInfo.Args = LocalInfo.Arguments; 550193267Sjkim LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr; 551193267Sjkim LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr; 552193267Sjkim LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr; 553193267Sjkim LocalInfo.Arguments[3] = NULL; 554193267Sjkim 555222544Sjkim LocalInfo.Types = LocalInfo.ArgTypes; 556222544Sjkim 557193267Sjkim (void) AcpiOsSignalSemaphore (Info->InfoGate, 1); 558193267Sjkim 55967754Smsmith for (i = 0; i < Info->NumLoops; i++) 56067754Smsmith { 561193267Sjkim Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj); 562117521Snjl if (ACPI_FAILURE (Status)) 56367754Smsmith { 564240716Sjkim AcpiOsPrintf ("%s During evaluation of %s at iteration %X\n", 565117521Snjl AcpiFormatException (Status), Info->Pathname, i); 566127175Snjl if (Status == AE_ABORT_METHOD) 567127175Snjl { 568127175Snjl break; 569127175Snjl } 57067754Smsmith } 571117521Snjl 572167802Sjkim#if 0 573128212Snjl if ((i % 100) == 0) 574117521Snjl { 575240716Sjkim AcpiOsPrintf ("%u loops, Thread 0x%x\n", i, AcpiOsGetThreadId ()); 576117521Snjl } 577117521Snjl 578117521Snjl if (ReturnObj.Length) 579117521Snjl { 580240716Sjkim AcpiOsPrintf ("Evaluation of %s returned object %p Buflen %X\n", 581117521Snjl Info->Pathname, ReturnObj.Pointer, (UINT32) ReturnObj.Length); 582151937Sjkim AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 583117521Snjl } 584117521Snjl#endif 58567754Smsmith } 58667754Smsmith 58767754Smsmith /* Signal our completion */ 58867754Smsmith 589167802Sjkim Allow = 0; 590193267Sjkim (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 1, ACPI_WAIT_FOREVER); 591167802Sjkim Info->NumCompleted++; 592167802Sjkim 593167802Sjkim if (Info->NumCompleted == Info->NumThreads) 59499679Siwasaki { 595167802Sjkim /* Do signal for main thread once only */ 596167802Sjkim Allow = 1; 59799679Siwasaki } 598167802Sjkim 599193267Sjkim (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1); 600167802Sjkim 601167802Sjkim if (Allow) 602167802Sjkim { 603167802Sjkim Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1); 604167802Sjkim if (ACPI_FAILURE (Status)) 605167802Sjkim { 606167802Sjkim AcpiOsPrintf ("Could not signal debugger thread sync semaphore, %s\n", 607167802Sjkim AcpiFormatException (Status)); 608167802Sjkim } 609167802Sjkim } 61067754Smsmith} 61167754Smsmith 61267754Smsmith 61367754Smsmith/******************************************************************************* 61467754Smsmith * 61567754Smsmith * FUNCTION: AcpiDbCreateExecutionThreads 61667754Smsmith * 61767754Smsmith * PARAMETERS: NumThreadsArg - Number of threads to create 61867754Smsmith * NumLoopsArg - Loop count for the thread(s) 61967754Smsmith * MethodNameArg - Control method to execute 62067754Smsmith * 62167754Smsmith * RETURN: None 62267754Smsmith * 62367754Smsmith * DESCRIPTION: Create threads to execute method(s) 62467754Smsmith * 62567754Smsmith ******************************************************************************/ 62667754Smsmith 62767754Smsmithvoid 62867754SmsmithAcpiDbCreateExecutionThreads ( 629114237Snjl char *NumThreadsArg, 630114237Snjl char *NumLoopsArg, 631114237Snjl char *MethodNameArg) 63267754Smsmith{ 63367754Smsmith ACPI_STATUS Status; 63467754Smsmith UINT32 NumThreads; 63567754Smsmith UINT32 NumLoops; 63667754Smsmith UINT32 i; 637167802Sjkim UINT32 Size; 638167802Sjkim ACPI_MUTEX MainThreadGate; 639167802Sjkim ACPI_MUTEX ThreadCompleteGate; 640193267Sjkim ACPI_MUTEX InfoGate; 64167754Smsmith 642193267Sjkim 64367754Smsmith /* Get the arguments */ 64467754Smsmith 64591116Smsmith NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0); 64691116Smsmith NumLoops = ACPI_STRTOUL (NumLoopsArg, NULL, 0); 64767754Smsmith 64867754Smsmith if (!NumThreads || !NumLoops) 64967754Smsmith { 650151937Sjkim AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", 651151937Sjkim NumThreads, NumLoops); 65267754Smsmith return; 65367754Smsmith } 65467754Smsmith 655167802Sjkim /* 656167802Sjkim * Create the semaphore for synchronization of 657167802Sjkim * the created threads with the main thread. 658167802Sjkim */ 659167802Sjkim Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate); 660167802Sjkim if (ACPI_FAILURE (Status)) 661167802Sjkim { 662167802Sjkim AcpiOsPrintf ("Could not create semaphore for synchronization with the main thread, %s\n", 663167802Sjkim AcpiFormatException (Status)); 664167802Sjkim return; 665167802Sjkim } 66667754Smsmith 667167802Sjkim /* 668167802Sjkim * Create the semaphore for synchronization 669167802Sjkim * between the created threads. 670167802Sjkim */ 671167802Sjkim Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate); 67267754Smsmith if (ACPI_FAILURE (Status)) 67367754Smsmith { 674167802Sjkim AcpiOsPrintf ("Could not create semaphore for synchronization between the created threads, %s\n", 675151937Sjkim AcpiFormatException (Status)); 676167802Sjkim (void) AcpiOsDeleteSemaphore (MainThreadGate); 67767754Smsmith return; 67867754Smsmith } 67967754Smsmith 680193267Sjkim Status = AcpiOsCreateSemaphore (1, 1, &InfoGate); 681193267Sjkim if (ACPI_FAILURE (Status)) 682193267Sjkim { 683193267Sjkim AcpiOsPrintf ("Could not create semaphore for synchronization of AcpiGbl_DbMethodInfo, %s\n", 684193267Sjkim AcpiFormatException (Status)); 685193267Sjkim (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 686193267Sjkim (void) AcpiOsDeleteSemaphore (MainThreadGate); 687193267Sjkim return; 688193267Sjkim } 689193267Sjkim 690167802Sjkim ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 691167802Sjkim 692167802Sjkim /* Array to store IDs of threads */ 693167802Sjkim 694167802Sjkim AcpiGbl_DbMethodInfo.NumThreads = NumThreads; 695212761Sjkim Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads; 696212761Sjkim AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size); 697167802Sjkim if (AcpiGbl_DbMethodInfo.Threads == NULL) 698167802Sjkim { 699167802Sjkim AcpiOsPrintf ("No memory for thread IDs array\n"); 700167802Sjkim (void) AcpiOsDeleteSemaphore (MainThreadGate); 701167802Sjkim (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 702193267Sjkim (void) AcpiOsDeleteSemaphore (InfoGate); 703167802Sjkim return; 704167802Sjkim } 705167802Sjkim ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size); 706167802Sjkim 70767754Smsmith /* Setup the context to be passed to each thread */ 70867754Smsmith 70983174Smsmith AcpiGbl_DbMethodInfo.Name = MethodNameArg; 71083174Smsmith AcpiGbl_DbMethodInfo.Flags = 0; 71183174Smsmith AcpiGbl_DbMethodInfo.NumLoops = NumLoops; 712167802Sjkim AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate; 713167802Sjkim AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate; 714193267Sjkim AcpiGbl_DbMethodInfo.InfoGate = InfoGate; 71567754Smsmith 716167802Sjkim /* Init arguments to be passed to method */ 717167802Sjkim 718167802Sjkim AcpiGbl_DbMethodInfo.InitArgs = 1; 719167802Sjkim AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; 720167802Sjkim AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr; 721167802Sjkim AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr; 722167802Sjkim AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr; 723167802Sjkim AcpiGbl_DbMethodInfo.Arguments[3] = NULL; 724222544Sjkim 725222544Sjkim AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes; 726222544Sjkim AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER; 727222544Sjkim AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER; 728222544Sjkim AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER; 729222544Sjkim 730237412Sjkim AcpiDbUint32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr); 731167802Sjkim 73283174Smsmith AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 73367754Smsmith 734239340Sjkim /* Get the NS node, determines existence also */ 735239340Sjkim 736239340Sjkim Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 737239340Sjkim &AcpiGbl_DbMethodInfo.Method); 738239340Sjkim if (ACPI_FAILURE (Status)) 739239340Sjkim { 740239340Sjkim AcpiOsPrintf ("%s Could not get handle for %s\n", 741239340Sjkim AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname); 742239340Sjkim goto CleanupAndExit; 743239340Sjkim } 744239340Sjkim 74567754Smsmith /* Create the threads */ 74667754Smsmith 747151937Sjkim AcpiOsPrintf ("Creating %X threads to execute %X times each\n", 748151937Sjkim NumThreads, NumLoops); 74967754Smsmith 75067754Smsmith for (i = 0; i < (NumThreads); i++) 75167754Smsmith { 752167802Sjkim Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread, 753151937Sjkim &AcpiGbl_DbMethodInfo); 75499679Siwasaki if (ACPI_FAILURE (Status)) 75599679Siwasaki { 75699679Siwasaki break; 75799679Siwasaki } 75867754Smsmith } 75967754Smsmith 76067754Smsmith /* Wait for all threads to complete */ 76167754Smsmith 762193267Sjkim (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER); 76367754Smsmith 764167802Sjkim AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 765167802Sjkim AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); 766167802Sjkim AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 767167802Sjkim 768239340SjkimCleanupAndExit: 769239340Sjkim 77067754Smsmith /* Cleanup and exit */ 77167754Smsmith 772167802Sjkim (void) AcpiOsDeleteSemaphore (MainThreadGate); 773167802Sjkim (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 774193267Sjkim (void) AcpiOsDeleteSemaphore (InfoGate); 77567754Smsmith 776167802Sjkim AcpiOsFree (AcpiGbl_DbMethodInfo.Threads); 777167802Sjkim AcpiGbl_DbMethodInfo.Threads = NULL; 77867754Smsmith} 77967754Smsmith 780102550Siwasaki#endif /* ACPI_DEBUGGER */ 781