Add support for region address conflict checking.

Allows drivers to determine if any memory or I/O addresses will
conflict with addresses used by ACPI operation regions.
Introduces a new interface, AcpiCheckAddressRange.
This commit is contained in:
Robert Moore 2011-12-21 13:25:52 -08:00
parent 802c00cbee
commit 4bbeebf0a9
11 changed files with 512 additions and 2 deletions

View File

@ -498,5 +498,13 @@ AcpiDsGetRegionArguments (
Status = AcpiDsExecuteArguments (Node, ExtraDesc->Extra.ScopeNode,
ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
Status = AcpiUtAddAddressRange (ObjDesc->Region.SpaceId,
ObjDesc->Region.Address, ObjDesc->Region.Length,
Node);
return_ACPI_STATUS (Status);
}

View File

@ -0,0 +1,394 @@
/******************************************************************************
*
* Module Name: utaddress - OpRegion address range check
*
*****************************************************************************/
/******************************************************************************
*
* 1. Copyright Notice
*
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
* All rights reserved.
*
* 2. License
*
* 2.1. This is your license from Intel Corp. under its intellectual property
* rights. You may have additional license terms from the party that provided
* you this software, covering your right to use that party's intellectual
* property rights.
*
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
* copy of the source code appearing in this file ("Covered Code") an
* irrevocable, perpetual, worldwide license under Intel's copyrights in the
* base code distributed originally by Intel ("Original Intel Code") to copy,
* make derivatives, distribute, use and display any portion of the Covered
* Code in any form, with the right to sublicense such rights; and
*
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
* license (with the right to sublicense), under only those claims of Intel
* patents that are infringed by the Original Intel Code, to make, use, sell,
* offer to sell, and import the Covered Code and derivative works thereof
* solely to the minimum extent necessary to exercise the above copyright
* license, and in no event shall the patent license extend to any additions
* to or modifications of the Original Intel Code. No other license or right
* is granted directly or by implication, estoppel or otherwise;
*
* The above copyright and patent license is granted only if the following
* conditions are met:
*
* 3. Conditions
*
* 3.1. Redistribution of Source with Rights to Further Distribute Source.
* Redistribution of source code of any substantial portion of the Covered
* Code or modification with rights to further distribute source must include
* the above Copyright Notice, the above License, this list of Conditions,
* and the following Disclaimer and Export Compliance provision. In addition,
* Licensee must cause all Covered Code to which Licensee contributes to
* contain a file documenting the changes Licensee made to create that Covered
* Code and the date of any change. Licensee must include in that file the
* documentation of any changes made by any predecessor Licensee. Licensee
* must include a prominent statement that the modification is derived,
* directly or indirectly, from Original Intel Code.
*
* 3.2. Redistribution of Source with no Rights to Further Distribute Source.
* Redistribution of source code of any substantial portion of the Covered
* Code or modification without rights to further distribute source must
* include the following Disclaimer and Export Compliance provision in the
* documentation and/or other materials provided with distribution. In
* addition, Licensee may not authorize further sublicense of source of any
* portion of the Covered Code, and must include terms to the effect that the
* license from Licensee to its licensee is limited to the intellectual
* property embodied in the software Licensee provides to its licensee, and
* not to intellectual property embodied in modifications its licensee may
* make.
*
* 3.3. Redistribution of Executable. Redistribution in executable form of any
* substantial portion of the Covered Code or modification must reproduce the
* above Copyright Notice, and the following Disclaimer and Export Compliance
* provision in the documentation and/or other materials provided with the
* distribution.
*
* 3.4. Intel retains all right, title, and interest in and to the Original
* Intel Code.
*
* 3.5. Neither the name Intel nor any other trademark owned or controlled by
* Intel shall be used in advertising or otherwise to promote the sale, use or
* other dealings in products derived from or relating to the Covered Code
* without prior written authorization from Intel.
*
* 4. Disclaimer and Export Compliance
*
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
* LIMITED REMEDY.
*
* 4.3. Licensee shall not export, either directly or indirectly, any of this
* software or system incorporating such software without first obtaining any
* required license or other approval from the U. S. Department of Commerce or
* any other agency or department of the United States Government. In the
* event Licensee exports any such software from the United States or
* re-exports any such software from a foreign destination, Licensee shall
* ensure that the distribution and export/re-export of the software is in
* compliance with all laws, regulations, orders, or other restrictions of the
* U.S. Export Administration Regulations. Licensee agrees that neither it nor
* any of its subsidiaries will export/re-export any technical data, process,
* software, or service, directly or indirectly, to any country for which the
* United States government or any agency thereof requires an export license,
* other governmental approval, or letter of assurance, without first obtaining
* such license, approval or letter.
*
*****************************************************************************/
#define __UTADDRESS_C__
#include "acpi.h"
#include "accommon.h"
#include "acnamesp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ("utaddress")
/*******************************************************************************
*
* FUNCTION: AcpiUtAddAddressRange
*
* PARAMETERS: SpaceId - Address space ID
* Address - OpRegion start address
* Length - OpRegion length
* RegionNode - OpRegion namespace node
*
* RETURN: Status
*
* DESCRIPTION: Add the Operation Region address range to the global list.
* The only supported Space IDs are Memory and I/O. Called when
* the OpRegion address/length operands are fully evaluated.
*
* MUTEX: Locks the namespace
*
* NOTE: Because this interface is only called when an OpRegion argument
* list is evaluated, there cannot be any duplicate RegionNodes.
* Duplicate Address/Length values are allowed, however, so that multiple
* address conflicts can be detected.
*
******************************************************************************/
ACPI_STATUS
AcpiUtAddAddressRange (
ACPI_ADR_SPACE_TYPE SpaceId,
ACPI_PHYSICAL_ADDRESS Address,
UINT32 Length,
ACPI_NAMESPACE_NODE *RegionNode)
{
ACPI_ADDRESS_RANGE *RangeInfo;
ACPI_STATUS Status;
ACPI_FUNCTION_TRACE (UtAddAddressRange);
if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
(SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
{
return_ACPI_STATUS (AE_OK);
}
/* Allocate/init a new info block, add it to the appropriate list */
RangeInfo = ACPI_ALLOCATE (sizeof (ACPI_ADDRESS_RANGE));
if (!RangeInfo)
{
return_ACPI_STATUS (AE_NO_MEMORY);
}
RangeInfo->StartAddress = Address;
RangeInfo->EndAddress = (Address + Length - 1);
RangeInfo->RegionNode = RegionNode;
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (Status))
{
ACPI_FREE (RangeInfo);
return_ACPI_STATUS (Status);
}
RangeInfo->Next = AcpiGbl_AddressRangeList[SpaceId];
AcpiGbl_AddressRangeList[SpaceId] = RangeInfo;
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
"\nAdded [%4.4s] address range: 0x%p-0x%p\n",
AcpiUtGetNodeName (RangeInfo->RegionNode),
ACPI_CAST_PTR (void, Address),
ACPI_CAST_PTR (void, RangeInfo->EndAddress)));
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
return_ACPI_STATUS (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: AcpiUtRemoveAddressRange
*
* PARAMETERS: SpaceId - Address space ID
* RegionNode - OpRegion namespace node
*
* RETURN: None
*
* DESCRIPTION: Remove the Operation Region from the global list. The only
* supported Space IDs are Memory and I/O. Called when an
* OpRegion is deleted.
*
* MUTEX: Assumes the namespace is locked
*
******************************************************************************/
void
AcpiUtRemoveAddressRange (
ACPI_ADR_SPACE_TYPE SpaceId,
ACPI_NAMESPACE_NODE *RegionNode)
{
ACPI_ADDRESS_RANGE *RangeInfo;
ACPI_ADDRESS_RANGE *Prev;
ACPI_FUNCTION_TRACE (UtRemoveAddressRange);
if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
(SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
{
return_VOID;
}
/* Get the appropriate list head and check the list */
RangeInfo = Prev = AcpiGbl_AddressRangeList[SpaceId];
while (RangeInfo)
{
if (RangeInfo->RegionNode == RegionNode)
{
if (RangeInfo == Prev) /* Found at list head */
{
AcpiGbl_AddressRangeList[SpaceId] = RangeInfo->Next;
}
else
{
Prev->Next = RangeInfo->Next;
}
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
"\nRemoved [%4.4s] address range: 0x%p-0x%p\n",
AcpiUtGetNodeName (RangeInfo->RegionNode),
ACPI_CAST_PTR (void, RangeInfo->StartAddress),
ACPI_CAST_PTR (void, RangeInfo->EndAddress)));
ACPI_FREE (RangeInfo);
return_VOID;
}
Prev = RangeInfo;
RangeInfo = RangeInfo->Next;
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: AcpiUtCheckAddressRange
*
* PARAMETERS: SpaceId - Address space ID
* Address - Start address
* Length - Length of address range
* Warn - TRUE if warning on overlap desired
*
* RETURN: Count of the number of conflicts detected. Zero is always
* returned for Space IDs other than Memory or I/O.
*
* DESCRIPTION: Check if the input address range overlaps any of the
* ASL operation region address ranges. The only supported
* Space IDs are Memory and I/O.
*
* MUTEX: Assumes the namespace is locked.
*
******************************************************************************/
UINT32
AcpiUtCheckAddressRange (
ACPI_ADR_SPACE_TYPE SpaceId,
ACPI_PHYSICAL_ADDRESS Address,
UINT32 Length,
BOOLEAN Warn)
{
ACPI_ADDRESS_RANGE *RangeInfo;
ACPI_PHYSICAL_ADDRESS EndAddress;
char *Pathname;
UINT32 OverlapCount = 0;
ACPI_FUNCTION_TRACE (UtCheckAddressRange);
if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
(SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
{
return_UINT32 (0);
}
RangeInfo = AcpiGbl_AddressRangeList[SpaceId];
EndAddress = Address + Length - 1;
/* Check entire list for all possible conflicts */
while (RangeInfo)
{
/*
* Check if the requested Address/Length overlaps this AddressRange.
* Four cases to consider:
*
* 1) Input address/length is contained completely in the address range
* 2) Input address/length overlaps range at the range start
* 3) Input address/length overlaps range at the range end
* 4) Input address/length completely encompasses the range
*/
if ((Address <= RangeInfo->EndAddress) &&
(EndAddress >= RangeInfo->StartAddress))
{
/* Found an address range overlap */
OverlapCount++;
if (Warn) /* Optional warning message */
{
Pathname = AcpiNsGetExternalPathname (RangeInfo->RegionNode);
ACPI_WARNING ((AE_INFO,
"0x%p-0x%p %s conflicts with Region %s %d",
ACPI_CAST_PTR (void, Address),
ACPI_CAST_PTR (void, EndAddress),
AcpiUtGetRegionName (SpaceId), Pathname, OverlapCount));
ACPI_FREE (Pathname);
}
}
RangeInfo = RangeInfo->Next;
}
return_UINT32 (OverlapCount);
}
/*******************************************************************************
*
* FUNCTION: AcpiUtDeleteAddressLists
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Delete all global address range lists (called during
* subsystem shutdown).
*
******************************************************************************/
void
AcpiUtDeleteAddressLists (
void)
{
ACPI_ADDRESS_RANGE *Next;
ACPI_ADDRESS_RANGE *RangeInfo;
int i;
/* Delete all elements in all address range lists */
for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++)
{
Next = AcpiGbl_AddressRangeList[i];
while (Next)
{
RangeInfo = Next;
Next = RangeInfo->Next;
ACPI_FREE (RangeInfo);
}
AcpiGbl_AddressRangeList[i] = NULL;
}
}

View File

@ -307,6 +307,16 @@ AcpiUtDeleteInternalObj (
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
"***** Region %p\n", Object));
/*
* Update AddressRange list. However, only permanent regions
* are installed in this list. (Not created within a method)
*/
if (!(Object->Region.Node->Flags & ANOBJ_TEMPORARY))
{
AcpiUtRemoveAddressRange (Object->Region.SpaceId,
Object->Region.Node);
}
SecondDesc = AcpiNsGetSecondaryObject (Object);
if (SecondDesc)
{

View File

@ -305,6 +305,13 @@ AcpiUtInitGlobals (
return_ACPI_STATUS (Status);
}
/* Address Range lists */
for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++)
{
AcpiGbl_AddressRangeList[i] = NULL;
}
/* Mutex locked flags */
for (i = 0; i < ACPI_NUM_MUTEX; i++)

View File

@ -176,6 +176,7 @@ AcpiUtTerminate (
GpeXruptInfo = NextGpeXruptInfo;
}
AcpiUtDeleteAddressLists ();
return_VOID;
}

View File

@ -122,6 +122,7 @@
#include "acnamesp.h"
#include "acdebug.h"
#include "actables.h"
#include "acinterp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ("utxface")
@ -857,5 +858,47 @@ AcpiInstallInterfaceHandler (
ACPI_EXPORT_SYMBOL (AcpiInstallInterfaceHandler)
#endif /* !ACPI_ASL_COMPILER */
/*****************************************************************************
*
* FUNCTION: AcpiCheckAddressRange
*
* PARAMETERS: SpaceId - Address space ID
* Address - Start address
* Length - Length
* Warn - TRUE if warning on overlap desired
*
* RETURN: Count of the number of conflicts detected.
*
* DESCRIPTION: Check if the input address range overlaps any of the
* ASL operation region address ranges.
*
****************************************************************************/
UINT32
AcpiCheckAddressRange (
ACPI_ADR_SPACE_TYPE SpaceId,
ACPI_PHYSICAL_ADDRESS Address,
ACPI_SIZE Length,
BOOLEAN Warn)
{
UINT32 Overlaps;
ACPI_STATUS Status;
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (Status))
{
return (0);
}
Overlaps = AcpiUtCheckAddressRange (SpaceId, Address,
(UINT32) Length, Warn);
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
return (Overlaps);
}
ACPI_EXPORT_SYMBOL (AcpiCheckAddressRange)
#endif /* !ACPI_ASL_COMPILER */

View File

@ -197,6 +197,10 @@
#define ACPI_MAX_SLEEP 2000 /* 2000 millisec == two seconds */
/* Address Range lists are per-SpaceId (Memory and I/O only) */
#define ACPI_ADDRESS_RANGE_MAX 2
/******************************************************************************
*

View File

@ -355,6 +355,7 @@ ACPI_EXTERN BOOLEAN AcpiGbl_AcpiHardwarePresent;
ACPI_EXTERN BOOLEAN AcpiGbl_EventsInitialized;
ACPI_EXTERN UINT8 AcpiGbl_OsiData;
ACPI_EXTERN ACPI_INTERFACE_INFO *AcpiGbl_SupportedInterfaces;
ACPI_EXTERN ACPI_ADDRESS_RANGE *AcpiGbl_AddressRangeList[ACPI_ADDRESS_RANGE_MAX];
#ifndef DEFINE_ACPI_GLOBALS

View File

@ -827,6 +827,17 @@ typedef
ACPI_STATUS (*ACPI_EXECUTE_OP) (
struct acpi_walk_state *WalkState);
/* Address Range info block */
typedef struct acpi_address_range
{
struct acpi_address_range *Next;
ACPI_NAMESPACE_NODE *RegionNode;
ACPI_PHYSICAL_ADDRESS StartAddress;
ACPI_PHYSICAL_ADDRESS EndAddress;
} ACPI_ADDRESS_RANGE;
/*****************************************************************************
*

View File

@ -217,6 +217,13 @@ ACPI_STATUS
AcpiRemoveInterface (
ACPI_STRING InterfaceName);
UINT32
AcpiCheckAddressRange (
ACPI_ADR_SPACE_TYPE SpaceId,
ACPI_PHYSICAL_ADDRESS Address,
ACPI_SIZE Length,
BOOLEAN Warn);
/*
* ACPI Memory management

View File

@ -202,7 +202,6 @@ typedef struct acpi_pkg_info
#define DB_DWORD_DISPLAY 4
#define DB_QWORD_DISPLAY 8
/*
* utglobal - Global data structures and procedures
*/
@ -991,6 +990,31 @@ AcpiUtCreateList (
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
/*
* utaddress - address range check
*/
ACPI_STATUS
AcpiUtAddAddressRange (
ACPI_ADR_SPACE_TYPE SpaceId,
ACPI_PHYSICAL_ADDRESS Address,
UINT32 Length,
ACPI_NAMESPACE_NODE *RegionNode);
void
AcpiUtRemoveAddressRange (
ACPI_ADR_SPACE_TYPE SpaceId,
ACPI_NAMESPACE_NODE *RegionNode);
UINT32
AcpiUtCheckAddressRange (
ACPI_ADR_SPACE_TYPE SpaceId,
ACPI_PHYSICAL_ADDRESS Address,
UINT32 Length,
BOOLEAN Warn);
void
AcpiUtDeleteAddressLists (
void);
/*
* utxferror - various error/warning output functions