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

exregion.c (14585B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: exregion - ACPI default op_region (address space) handlers
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acinterp.h"
     13
     14#define _COMPONENT          ACPI_EXECUTER
     15ACPI_MODULE_NAME("exregion")
     16
     17/*******************************************************************************
     18 *
     19 * FUNCTION:    acpi_ex_system_memory_space_handler
     20 *
     21 * PARAMETERS:  function            - Read or Write operation
     22 *              address             - Where in the space to read or write
     23 *              bit_width           - Field width in bits (8, 16, or 32)
     24 *              value               - Pointer to in or out value
     25 *              handler_context     - Pointer to Handler's context
     26 *              region_context      - Pointer to context specific to the
     27 *                                    accessed region
     28 *
     29 * RETURN:      Status
     30 *
     31 * DESCRIPTION: Handler for the System Memory address space (Op Region)
     32 *
     33 ******************************************************************************/
     34acpi_status
     35acpi_ex_system_memory_space_handler(u32 function,
     36				    acpi_physical_address address,
     37				    u32 bit_width,
     38				    u64 *value,
     39				    void *handler_context, void *region_context)
     40{
     41	acpi_status status = AE_OK;
     42	void *logical_addr_ptr = NULL;
     43	struct acpi_mem_space_context *mem_info = region_context;
     44	struct acpi_mem_mapping *mm = mem_info->cur_mm;
     45	u32 length;
     46	acpi_size map_length;
     47	acpi_size page_boundary_map_length;
     48#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
     49	u32 remainder;
     50#endif
     51
     52	ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
     53
     54	/* Validate and translate the bit width */
     55
     56	switch (bit_width) {
     57	case 8:
     58
     59		length = 1;
     60		break;
     61
     62	case 16:
     63
     64		length = 2;
     65		break;
     66
     67	case 32:
     68
     69		length = 4;
     70		break;
     71
     72	case 64:
     73
     74		length = 8;
     75		break;
     76
     77	default:
     78
     79		ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u",
     80			    bit_width));
     81		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
     82	}
     83
     84#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
     85	/*
     86	 * Hardware does not support non-aligned data transfers, we must verify
     87	 * the request.
     88	 */
     89	(void)acpi_ut_short_divide((u64) address, length, NULL, &remainder);
     90	if (remainder != 0) {
     91		return_ACPI_STATUS(AE_AML_ALIGNMENT);
     92	}
     93#endif
     94
     95	/*
     96	 * Does the request fit into the cached memory mapping?
     97	 * Is 1) Address below the current mapping? OR
     98	 *    2) Address beyond the current mapping?
     99	 */
    100	if (!mm || (address < mm->physical_address) ||
    101	    ((u64) address + length > (u64) mm->physical_address + mm->length)) {
    102		/*
    103		 * The request cannot be resolved by the current memory mapping.
    104		 *
    105		 * Look for an existing saved mapping covering the address range
    106		 * at hand.  If found, save it as the current one and carry out
    107		 * the access.
    108		 */
    109		for (mm = mem_info->first_mm; mm; mm = mm->next_mm) {
    110			if (mm == mem_info->cur_mm)
    111				continue;
    112
    113			if (address < mm->physical_address)
    114				continue;
    115
    116			if ((u64) address + length >
    117					(u64) mm->physical_address + mm->length)
    118				continue;
    119
    120			mem_info->cur_mm = mm;
    121			goto access;
    122		}
    123
    124		/* Create a new mappings list entry */
    125		mm = ACPI_ALLOCATE_ZEROED(sizeof(*mm));
    126		if (!mm) {
    127			ACPI_ERROR((AE_INFO,
    128				    "Unable to save memory mapping at 0x%8.8X%8.8X, size %u",
    129				    ACPI_FORMAT_UINT64(address), length));
    130			return_ACPI_STATUS(AE_NO_MEMORY);
    131		}
    132
    133		/*
    134		 * October 2009: Attempt to map from the requested address to the
    135		 * end of the region. However, we will never map more than one
    136		 * page, nor will we cross a page boundary.
    137		 */
    138		map_length = (acpi_size)
    139		    ((mem_info->address + mem_info->length) - address);
    140
    141		/*
    142		 * If mapping the entire remaining portion of the region will cross
    143		 * a page boundary, just map up to the page boundary, do not cross.
    144		 * On some systems, crossing a page boundary while mapping regions
    145		 * can cause warnings if the pages have different attributes
    146		 * due to resource management.
    147		 *
    148		 * This has the added benefit of constraining a single mapping to
    149		 * one page, which is similar to the original code that used a 4k
    150		 * maximum window.
    151		 */
    152		page_boundary_map_length = (acpi_size)
    153		    (ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address);
    154		if (page_boundary_map_length == 0) {
    155			page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE;
    156		}
    157
    158		if (map_length > page_boundary_map_length) {
    159			map_length = page_boundary_map_length;
    160		}
    161
    162		/* Create a new mapping starting at the address given */
    163
    164		logical_addr_ptr = acpi_os_map_memory(address, map_length);
    165		if (!logical_addr_ptr) {
    166			ACPI_ERROR((AE_INFO,
    167				    "Could not map memory at 0x%8.8X%8.8X, size %u",
    168				    ACPI_FORMAT_UINT64(address),
    169				    (u32)map_length));
    170			ACPI_FREE(mm);
    171			return_ACPI_STATUS(AE_NO_MEMORY);
    172		}
    173
    174		/* Save the physical address and mapping size */
    175
    176		mm->logical_address = logical_addr_ptr;
    177		mm->physical_address = address;
    178		mm->length = map_length;
    179
    180		/*
    181		 * Add the new entry to the mappigs list and save it as the
    182		 * current mapping.
    183		 */
    184		mm->next_mm = mem_info->first_mm;
    185		mem_info->first_mm = mm;
    186
    187		mem_info->cur_mm = mm;
    188	}
    189
    190access:
    191	/*
    192	 * Generate a logical pointer corresponding to the address we want to
    193	 * access
    194	 */
    195	logical_addr_ptr = mm->logical_address +
    196		((u64) address - (u64) mm->physical_address);
    197
    198	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
    199			  "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
    200			  bit_width, function, ACPI_FORMAT_UINT64(address)));
    201
    202	/*
    203	 * Perform the memory read or write
    204	 *
    205	 * Note: For machines that do not support non-aligned transfers, the target
    206	 * address was checked for alignment above. We do not attempt to break the
    207	 * transfer up into smaller (byte-size) chunks because the AML specifically
    208	 * asked for a transfer width that the hardware may require.
    209	 */
    210	switch (function) {
    211	case ACPI_READ:
    212
    213		*value = 0;
    214		switch (bit_width) {
    215		case 8:
    216
    217			*value = (u64)ACPI_GET8(logical_addr_ptr);
    218			break;
    219
    220		case 16:
    221
    222			*value = (u64)ACPI_GET16(logical_addr_ptr);
    223			break;
    224
    225		case 32:
    226
    227			*value = (u64)ACPI_GET32(logical_addr_ptr);
    228			break;
    229
    230		case 64:
    231
    232			*value = (u64)ACPI_GET64(logical_addr_ptr);
    233			break;
    234
    235		default:
    236
    237			/* bit_width was already validated */
    238
    239			break;
    240		}
    241		break;
    242
    243	case ACPI_WRITE:
    244
    245		switch (bit_width) {
    246		case 8:
    247
    248			ACPI_SET8(logical_addr_ptr, *value);
    249			break;
    250
    251		case 16:
    252
    253			ACPI_SET16(logical_addr_ptr, *value);
    254			break;
    255
    256		case 32:
    257
    258			ACPI_SET32(logical_addr_ptr, *value);
    259			break;
    260
    261		case 64:
    262
    263			ACPI_SET64(logical_addr_ptr, *value);
    264			break;
    265
    266		default:
    267
    268			/* bit_width was already validated */
    269
    270			break;
    271		}
    272		break;
    273
    274	default:
    275
    276		status = AE_BAD_PARAMETER;
    277		break;
    278	}
    279
    280	return_ACPI_STATUS(status);
    281}
    282
    283/*******************************************************************************
    284 *
    285 * FUNCTION:    acpi_ex_system_io_space_handler
    286 *
    287 * PARAMETERS:  function            - Read or Write operation
    288 *              address             - Where in the space to read or write
    289 *              bit_width           - Field width in bits (8, 16, or 32)
    290 *              value               - Pointer to in or out value
    291 *              handler_context     - Pointer to Handler's context
    292 *              region_context      - Pointer to context specific to the
    293 *                                    accessed region
    294 *
    295 * RETURN:      Status
    296 *
    297 * DESCRIPTION: Handler for the System IO address space (Op Region)
    298 *
    299 ******************************************************************************/
    300
    301acpi_status
    302acpi_ex_system_io_space_handler(u32 function,
    303				acpi_physical_address address,
    304				u32 bit_width,
    305				u64 *value,
    306				void *handler_context, void *region_context)
    307{
    308	acpi_status status = AE_OK;
    309	u32 value32;
    310
    311	ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
    312
    313	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
    314			  "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
    315			  bit_width, function, ACPI_FORMAT_UINT64(address)));
    316
    317	/* Decode the function parameter */
    318
    319	switch (function) {
    320	case ACPI_READ:
    321
    322		status = acpi_hw_read_port((acpi_io_address)address,
    323					   &value32, bit_width);
    324		*value = value32;
    325		break;
    326
    327	case ACPI_WRITE:
    328
    329		status = acpi_hw_write_port((acpi_io_address)address,
    330					    (u32)*value, bit_width);
    331		break;
    332
    333	default:
    334
    335		status = AE_BAD_PARAMETER;
    336		break;
    337	}
    338
    339	return_ACPI_STATUS(status);
    340}
    341
    342#ifdef ACPI_PCI_CONFIGURED
    343/*******************************************************************************
    344 *
    345 * FUNCTION:    acpi_ex_pci_config_space_handler
    346 *
    347 * PARAMETERS:  function            - Read or Write operation
    348 *              address             - Where in the space to read or write
    349 *              bit_width           - Field width in bits (8, 16, or 32)
    350 *              value               - Pointer to in or out value
    351 *              handler_context     - Pointer to Handler's context
    352 *              region_context      - Pointer to context specific to the
    353 *                                    accessed region
    354 *
    355 * RETURN:      Status
    356 *
    357 * DESCRIPTION: Handler for the PCI Config address space (Op Region)
    358 *
    359 ******************************************************************************/
    360
    361acpi_status
    362acpi_ex_pci_config_space_handler(u32 function,
    363				 acpi_physical_address address,
    364				 u32 bit_width,
    365				 u64 *value,
    366				 void *handler_context, void *region_context)
    367{
    368	acpi_status status = AE_OK;
    369	struct acpi_pci_id *pci_id;
    370	u16 pci_register;
    371
    372	ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
    373
    374	/*
    375	 *  The arguments to acpi_os(Read|Write)pci_configuration are:
    376	 *
    377	 *  pci_segment is the PCI bus segment range 0-31
    378	 *  pci_bus     is the PCI bus number range 0-255
    379	 *  pci_device  is the PCI device number range 0-31
    380	 *  pci_function is the PCI device function number
    381	 *  pci_register is the Config space register range 0-255 bytes
    382	 *
    383	 *  value - input value for write, output address for read
    384	 *
    385	 */
    386	pci_id = (struct acpi_pci_id *)region_context;
    387	pci_register = (u16) (u32) address;
    388
    389	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
    390			  "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
    391			  "Dev(%04x) Func(%04x) Reg(%04x)\n",
    392			  function, bit_width, pci_id->segment, pci_id->bus,
    393			  pci_id->device, pci_id->function, pci_register));
    394
    395	switch (function) {
    396	case ACPI_READ:
    397
    398		*value = 0;
    399		status =
    400		    acpi_os_read_pci_configuration(pci_id, pci_register, value,
    401						   bit_width);
    402		break;
    403
    404	case ACPI_WRITE:
    405
    406		status =
    407		    acpi_os_write_pci_configuration(pci_id, pci_register,
    408						    *value, bit_width);
    409		break;
    410
    411	default:
    412
    413		status = AE_BAD_PARAMETER;
    414		break;
    415	}
    416
    417	return_ACPI_STATUS(status);
    418}
    419#endif
    420
    421/*******************************************************************************
    422 *
    423 * FUNCTION:    acpi_ex_cmos_space_handler
    424 *
    425 * PARAMETERS:  function            - Read or Write operation
    426 *              address             - Where in the space to read or write
    427 *              bit_width           - Field width in bits (8, 16, or 32)
    428 *              value               - Pointer to in or out value
    429 *              handler_context     - Pointer to Handler's context
    430 *              region_context      - Pointer to context specific to the
    431 *                                    accessed region
    432 *
    433 * RETURN:      Status
    434 *
    435 * DESCRIPTION: Handler for the CMOS address space (Op Region)
    436 *
    437 ******************************************************************************/
    438
    439acpi_status
    440acpi_ex_cmos_space_handler(u32 function,
    441			   acpi_physical_address address,
    442			   u32 bit_width,
    443			   u64 *value,
    444			   void *handler_context, void *region_context)
    445{
    446	acpi_status status = AE_OK;
    447
    448	ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
    449
    450	return_ACPI_STATUS(status);
    451}
    452
    453#ifdef ACPI_PCI_CONFIGURED
    454/*******************************************************************************
    455 *
    456 * FUNCTION:    acpi_ex_pci_bar_space_handler
    457 *
    458 * PARAMETERS:  function            - Read or Write operation
    459 *              address             - Where in the space to read or write
    460 *              bit_width           - Field width in bits (8, 16, or 32)
    461 *              value               - Pointer to in or out value
    462 *              handler_context     - Pointer to Handler's context
    463 *              region_context      - Pointer to context specific to the
    464 *                                    accessed region
    465 *
    466 * RETURN:      Status
    467 *
    468 * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
    469 *
    470 ******************************************************************************/
    471
    472acpi_status
    473acpi_ex_pci_bar_space_handler(u32 function,
    474			      acpi_physical_address address,
    475			      u32 bit_width,
    476			      u64 *value,
    477			      void *handler_context, void *region_context)
    478{
    479	acpi_status status = AE_OK;
    480
    481	ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
    482
    483	return_ACPI_STATUS(status);
    484}
    485#endif
    486
    487/*******************************************************************************
    488 *
    489 * FUNCTION:    acpi_ex_data_table_space_handler
    490 *
    491 * PARAMETERS:  function            - Read or Write operation
    492 *              address             - Where in the space to read or write
    493 *              bit_width           - Field width in bits (8, 16, or 32)
    494 *              value               - Pointer to in or out value
    495 *              handler_context     - Pointer to Handler's context
    496 *              region_context      - Pointer to context specific to the
    497 *                                    accessed region
    498 *
    499 * RETURN:      Status
    500 *
    501 * DESCRIPTION: Handler for the Data Table address space (Op Region)
    502 *
    503 ******************************************************************************/
    504
    505acpi_status
    506acpi_ex_data_table_space_handler(u32 function,
    507				 acpi_physical_address address,
    508				 u32 bit_width,
    509				 u64 *value,
    510				 void *handler_context, void *region_context)
    511{
    512	struct acpi_data_table_space_context *mapping;
    513	char *pointer;
    514
    515	ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
    516
    517	mapping = (struct acpi_data_table_space_context *) region_context;
    518	pointer = ACPI_CAST_PTR(char, mapping->pointer) +
    519	    (address - ACPI_PTR_TO_PHYSADDR(mapping->pointer));
    520
    521	/*
    522	 * Perform the memory read or write. The bit_width was already
    523	 * validated.
    524	 */
    525	switch (function) {
    526	case ACPI_READ:
    527
    528		memcpy(ACPI_CAST_PTR(char, value), pointer,
    529		       ACPI_DIV_8(bit_width));
    530		break;
    531
    532	case ACPI_WRITE:
    533
    534		memcpy(pointer, ACPI_CAST_PTR(char, value),
    535		       ACPI_DIV_8(bit_width));
    536		break;
    537
    538	default:
    539
    540		return_ACPI_STATUS(AE_BAD_PARAMETER);
    541	}
    542
    543	return_ACPI_STATUS(AE_OK);
    544}