cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

utaddress.c (7738B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: utaddress - op_region address range check
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acnamesp.h"
     13
     14#define _COMPONENT          ACPI_UTILITIES
     15ACPI_MODULE_NAME("utaddress")
     16
     17/*******************************************************************************
     18 *
     19 * FUNCTION:    acpi_ut_add_address_range
     20 *
     21 * PARAMETERS:  space_id            - Address space ID
     22 *              address             - op_region start address
     23 *              length              - op_region length
     24 *              region_node         - op_region namespace node
     25 *
     26 * RETURN:      Status
     27 *
     28 * DESCRIPTION: Add the Operation Region address range to the global list.
     29 *              The only supported Space IDs are Memory and I/O. Called when
     30 *              the op_region address/length operands are fully evaluated.
     31 *
     32 * MUTEX:       Locks the namespace
     33 *
     34 * NOTE: Because this interface is only called when an op_region argument
     35 * list is evaluated, there cannot be any duplicate region_nodes.
     36 * Duplicate Address/Length values are allowed, however, so that multiple
     37 * address conflicts can be detected.
     38 *
     39 ******************************************************************************/
     40acpi_status
     41acpi_ut_add_address_range(acpi_adr_space_type space_id,
     42			  acpi_physical_address address,
     43			  u32 length, struct acpi_namespace_node *region_node)
     44{
     45	struct acpi_address_range *range_info;
     46
     47	ACPI_FUNCTION_TRACE(ut_add_address_range);
     48
     49	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
     50	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
     51		return_ACPI_STATUS(AE_OK);
     52	}
     53
     54	/* Allocate/init a new info block, add it to the appropriate list */
     55
     56	range_info = ACPI_ALLOCATE(sizeof(struct acpi_address_range));
     57	if (!range_info) {
     58		return_ACPI_STATUS(AE_NO_MEMORY);
     59	}
     60
     61	range_info->start_address = address;
     62	range_info->end_address = (address + length - 1);
     63	range_info->region_node = region_node;
     64
     65	range_info->next = acpi_gbl_address_range_list[space_id];
     66	acpi_gbl_address_range_list[space_id] = range_info;
     67
     68	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
     69			  "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",
     70			  acpi_ut_get_node_name(range_info->region_node),
     71			  ACPI_FORMAT_UINT64(address),
     72			  ACPI_FORMAT_UINT64(range_info->end_address)));
     73
     74	return_ACPI_STATUS(AE_OK);
     75}
     76
     77/*******************************************************************************
     78 *
     79 * FUNCTION:    acpi_ut_remove_address_range
     80 *
     81 * PARAMETERS:  space_id            - Address space ID
     82 *              region_node         - op_region namespace node
     83 *
     84 * RETURN:      None
     85 *
     86 * DESCRIPTION: Remove the Operation Region from the global list. The only
     87 *              supported Space IDs are Memory and I/O. Called when an
     88 *              op_region is deleted.
     89 *
     90 * MUTEX:       Assumes the namespace is locked
     91 *
     92 ******************************************************************************/
     93
     94void
     95acpi_ut_remove_address_range(acpi_adr_space_type space_id,
     96			     struct acpi_namespace_node *region_node)
     97{
     98	struct acpi_address_range *range_info;
     99	struct acpi_address_range *prev;
    100
    101	ACPI_FUNCTION_TRACE(ut_remove_address_range);
    102
    103	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
    104	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
    105		return_VOID;
    106	}
    107
    108	/* Get the appropriate list head and check the list */
    109
    110	range_info = prev = acpi_gbl_address_range_list[space_id];
    111	while (range_info) {
    112		if (range_info->region_node == region_node) {
    113			if (range_info == prev) {	/* Found at list head */
    114				acpi_gbl_address_range_list[space_id] =
    115				    range_info->next;
    116			} else {
    117				prev->next = range_info->next;
    118			}
    119
    120			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
    121					  "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",
    122					  acpi_ut_get_node_name(range_info->
    123								region_node),
    124					  ACPI_FORMAT_UINT64(range_info->
    125							     start_address),
    126					  ACPI_FORMAT_UINT64(range_info->
    127							     end_address)));
    128
    129			ACPI_FREE(range_info);
    130			return_VOID;
    131		}
    132
    133		prev = range_info;
    134		range_info = range_info->next;
    135	}
    136
    137	return_VOID;
    138}
    139
    140/*******************************************************************************
    141 *
    142 * FUNCTION:    acpi_ut_check_address_range
    143 *
    144 * PARAMETERS:  space_id            - Address space ID
    145 *              address             - Start address
    146 *              length              - Length of address range
    147 *              warn                - TRUE if warning on overlap desired
    148 *
    149 * RETURN:      Count of the number of conflicts detected. Zero is always
    150 *              returned for Space IDs other than Memory or I/O.
    151 *
    152 * DESCRIPTION: Check if the input address range overlaps any of the
    153 *              ASL operation region address ranges. The only supported
    154 *              Space IDs are Memory and I/O.
    155 *
    156 * MUTEX:       Assumes the namespace is locked.
    157 *
    158 ******************************************************************************/
    159
    160u32
    161acpi_ut_check_address_range(acpi_adr_space_type space_id,
    162			    acpi_physical_address address, u32 length, u8 warn)
    163{
    164	struct acpi_address_range *range_info;
    165	acpi_physical_address end_address;
    166	char *pathname;
    167	u32 overlap_count = 0;
    168
    169	ACPI_FUNCTION_TRACE(ut_check_address_range);
    170
    171	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
    172	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
    173		return_UINT32(0);
    174	}
    175
    176	range_info = acpi_gbl_address_range_list[space_id];
    177	end_address = address + length - 1;
    178
    179	/* Check entire list for all possible conflicts */
    180
    181	while (range_info) {
    182		/*
    183		 * Check if the requested address/length overlaps this
    184		 * address range. There are four cases to consider:
    185		 *
    186		 * 1) Input address/length is contained completely in the
    187		 *    address range
    188		 * 2) Input address/length overlaps range at the range start
    189		 * 3) Input address/length overlaps range at the range end
    190		 * 4) Input address/length completely encompasses the range
    191		 */
    192		if ((address <= range_info->end_address) &&
    193		    (end_address >= range_info->start_address)) {
    194
    195			/* Found an address range overlap */
    196
    197			overlap_count++;
    198			if (warn) {	/* Optional warning message */
    199				pathname =
    200				    acpi_ns_get_normalized_pathname(range_info->
    201								    region_node,
    202								    TRUE);
    203
    204				ACPI_WARNING((AE_INFO,
    205					      "%s range 0x%8.8X%8.8X-0x%8.8X%8.8X conflicts with OpRegion 0x%8.8X%8.8X-0x%8.8X%8.8X (%s)",
    206					      acpi_ut_get_region_name(space_id),
    207					      ACPI_FORMAT_UINT64(address),
    208					      ACPI_FORMAT_UINT64(end_address),
    209					      ACPI_FORMAT_UINT64(range_info->
    210								 start_address),
    211					      ACPI_FORMAT_UINT64(range_info->
    212								 end_address),
    213					      pathname));
    214				ACPI_FREE(pathname);
    215			}
    216		}
    217
    218		range_info = range_info->next;
    219	}
    220
    221	return_UINT32(overlap_count);
    222}
    223
    224/*******************************************************************************
    225 *
    226 * FUNCTION:    acpi_ut_delete_address_lists
    227 *
    228 * PARAMETERS:  None
    229 *
    230 * RETURN:      None
    231 *
    232 * DESCRIPTION: Delete all global address range lists (called during
    233 *              subsystem shutdown).
    234 *
    235 ******************************************************************************/
    236
    237void acpi_ut_delete_address_lists(void)
    238{
    239	struct acpi_address_range *next;
    240	struct acpi_address_range *range_info;
    241	int i;
    242
    243	/* Delete all elements in all address range lists */
    244
    245	for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
    246		next = acpi_gbl_address_range_list[i];
    247
    248		while (next) {
    249			range_info = next;
    250			next = range_info->next;
    251			ACPI_FREE(range_info);
    252		}
    253
    254		acpi_gbl_address_range_list[i] = NULL;
    255	}
    256}