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

rsxface.c (19649B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/*******************************************************************************
      3 *
      4 * Module Name: rsxface - Public interfaces to the resource manager
      5 *
      6 ******************************************************************************/
      7
      8#define EXPORT_ACPI_INTERFACES
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acresrc.h"
     13#include "acnamesp.h"
     14
     15#define _COMPONENT          ACPI_RESOURCES
     16ACPI_MODULE_NAME("rsxface")
     17
     18/* Local macros for 16,32-bit to 64-bit conversion */
     19#define ACPI_COPY_FIELD(out, in, field)  ((out)->field = (in)->field)
     20#define ACPI_COPY_ADDRESS(out, in)                       \
     21	ACPI_COPY_FIELD(out, in, resource_type);             \
     22	ACPI_COPY_FIELD(out, in, producer_consumer);         \
     23	ACPI_COPY_FIELD(out, in, decode);                    \
     24	ACPI_COPY_FIELD(out, in, min_address_fixed);         \
     25	ACPI_COPY_FIELD(out, in, max_address_fixed);         \
     26	ACPI_COPY_FIELD(out, in, info);                      \
     27	ACPI_COPY_FIELD(out, in, address.granularity);       \
     28	ACPI_COPY_FIELD(out, in, address.minimum);           \
     29	ACPI_COPY_FIELD(out, in, address.maximum);           \
     30	ACPI_COPY_FIELD(out, in, address.translation_offset); \
     31	ACPI_COPY_FIELD(out, in, address.address_length);    \
     32	ACPI_COPY_FIELD(out, in, resource_source);
     33/* Local prototypes */
     34static acpi_status
     35acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);
     36
     37static acpi_status
     38acpi_rs_validate_parameters(acpi_handle device_handle,
     39			    struct acpi_buffer *buffer,
     40			    struct acpi_namespace_node **return_node);
     41
     42/*******************************************************************************
     43 *
     44 * FUNCTION:    acpi_rs_validate_parameters
     45 *
     46 * PARAMETERS:  device_handle   - Handle to a device
     47 *              buffer          - Pointer to a data buffer
     48 *              return_node     - Pointer to where the device node is returned
     49 *
     50 * RETURN:      Status
     51 *
     52 * DESCRIPTION: Common parameter validation for resource interfaces
     53 *
     54 ******************************************************************************/
     55
     56static acpi_status
     57acpi_rs_validate_parameters(acpi_handle device_handle,
     58			    struct acpi_buffer *buffer,
     59			    struct acpi_namespace_node **return_node)
     60{
     61	acpi_status status;
     62	struct acpi_namespace_node *node;
     63
     64	ACPI_FUNCTION_TRACE(rs_validate_parameters);
     65
     66	/*
     67	 * Must have a valid handle to an ACPI device
     68	 */
     69	if (!device_handle) {
     70		return_ACPI_STATUS(AE_BAD_PARAMETER);
     71	}
     72
     73	node = acpi_ns_validate_handle(device_handle);
     74	if (!node) {
     75		return_ACPI_STATUS(AE_BAD_PARAMETER);
     76	}
     77
     78	if (node->type != ACPI_TYPE_DEVICE) {
     79		return_ACPI_STATUS(AE_TYPE);
     80	}
     81
     82	/*
     83	 * Validate the user buffer object
     84	 *
     85	 * if there is a non-zero buffer length we also need a valid pointer in
     86	 * the buffer. If it's a zero buffer length, we'll be returning the
     87	 * needed buffer size (later), so keep going.
     88	 */
     89	status = acpi_ut_validate_buffer(buffer);
     90	if (ACPI_FAILURE(status)) {
     91		return_ACPI_STATUS(status);
     92	}
     93
     94	*return_node = node;
     95	return_ACPI_STATUS(AE_OK);
     96}
     97
     98/*******************************************************************************
     99 *
    100 * FUNCTION:    acpi_get_irq_routing_table
    101 *
    102 * PARAMETERS:  device_handle   - Handle to the Bus device we are querying
    103 *              ret_buffer      - Pointer to a buffer to receive the
    104 *                                current resources for the device
    105 *
    106 * RETURN:      Status
    107 *
    108 * DESCRIPTION: This function is called to get the IRQ routing table for a
    109 *              specific bus. The caller must first acquire a handle for the
    110 *              desired bus. The routine table is placed in the buffer pointed
    111 *              to by the ret_buffer variable parameter.
    112 *
    113 *              If the function fails an appropriate status will be returned
    114 *              and the value of ret_buffer is undefined.
    115 *
    116 *              This function attempts to execute the _PRT method contained in
    117 *              the object indicated by the passed device_handle.
    118 *
    119 ******************************************************************************/
    120
    121acpi_status
    122acpi_get_irq_routing_table(acpi_handle device_handle,
    123			   struct acpi_buffer *ret_buffer)
    124{
    125	acpi_status status;
    126	struct acpi_namespace_node *node;
    127
    128	ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table);
    129
    130	/* Validate parameters then dispatch to internal routine */
    131
    132	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
    133	if (ACPI_FAILURE(status)) {
    134		return_ACPI_STATUS(status);
    135	}
    136
    137	status = acpi_rs_get_prt_method_data(node, ret_buffer);
    138	return_ACPI_STATUS(status);
    139}
    140
    141ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table)
    142
    143/*******************************************************************************
    144 *
    145 * FUNCTION:    acpi_get_current_resources
    146 *
    147 * PARAMETERS:  device_handle   - Handle to the device object for the
    148 *                                device we are querying
    149 *              ret_buffer      - Pointer to a buffer to receive the
    150 *                                current resources for the device
    151 *
    152 * RETURN:      Status
    153 *
    154 * DESCRIPTION: This function is called to get the current resources for a
    155 *              specific device. The caller must first acquire a handle for
    156 *              the desired device. The resource data is placed in the buffer
    157 *              pointed to by the ret_buffer variable parameter.
    158 *
    159 *              If the function fails an appropriate status will be returned
    160 *              and the value of ret_buffer is undefined.
    161 *
    162 *              This function attempts to execute the _CRS method contained in
    163 *              the object indicated by the passed device_handle.
    164 *
    165 ******************************************************************************/
    166acpi_status
    167acpi_get_current_resources(acpi_handle device_handle,
    168			   struct acpi_buffer *ret_buffer)
    169{
    170	acpi_status status;
    171	struct acpi_namespace_node *node;
    172
    173	ACPI_FUNCTION_TRACE(acpi_get_current_resources);
    174
    175	/* Validate parameters then dispatch to internal routine */
    176
    177	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
    178	if (ACPI_FAILURE(status)) {
    179		return_ACPI_STATUS(status);
    180	}
    181
    182	status = acpi_rs_get_crs_method_data(node, ret_buffer);
    183	return_ACPI_STATUS(status);
    184}
    185
    186ACPI_EXPORT_SYMBOL(acpi_get_current_resources)
    187
    188/*******************************************************************************
    189 *
    190 * FUNCTION:    acpi_get_possible_resources
    191 *
    192 * PARAMETERS:  device_handle   - Handle to the device object for the
    193 *                                device we are querying
    194 *              ret_buffer      - Pointer to a buffer to receive the
    195 *                                resources for the device
    196 *
    197 * RETURN:      Status
    198 *
    199 * DESCRIPTION: This function is called to get a list of the possible resources
    200 *              for a specific device. The caller must first acquire a handle
    201 *              for the desired device. The resource data is placed in the
    202 *              buffer pointed to by the ret_buffer variable.
    203 *
    204 *              If the function fails an appropriate status will be returned
    205 *              and the value of ret_buffer is undefined.
    206 *
    207 ******************************************************************************/
    208acpi_status
    209acpi_get_possible_resources(acpi_handle device_handle,
    210			    struct acpi_buffer *ret_buffer)
    211{
    212	acpi_status status;
    213	struct acpi_namespace_node *node;
    214
    215	ACPI_FUNCTION_TRACE(acpi_get_possible_resources);
    216
    217	/* Validate parameters then dispatch to internal routine */
    218
    219	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
    220	if (ACPI_FAILURE(status)) {
    221		return_ACPI_STATUS(status);
    222	}
    223
    224	status = acpi_rs_get_prs_method_data(node, ret_buffer);
    225	return_ACPI_STATUS(status);
    226}
    227
    228ACPI_EXPORT_SYMBOL(acpi_get_possible_resources)
    229
    230/*******************************************************************************
    231 *
    232 * FUNCTION:    acpi_set_current_resources
    233 *
    234 * PARAMETERS:  device_handle   - Handle to the device object for the
    235 *                                device we are setting resources
    236 *              in_buffer       - Pointer to a buffer containing the
    237 *                                resources to be set for the device
    238 *
    239 * RETURN:      Status
    240 *
    241 * DESCRIPTION: This function is called to set the current resources for a
    242 *              specific device. The caller must first acquire a handle for
    243 *              the desired device. The resource data is passed to the routine
    244 *              the buffer pointed to by the in_buffer variable.
    245 *
    246 ******************************************************************************/
    247acpi_status
    248acpi_set_current_resources(acpi_handle device_handle,
    249			   struct acpi_buffer *in_buffer)
    250{
    251	acpi_status status;
    252	struct acpi_namespace_node *node;
    253
    254	ACPI_FUNCTION_TRACE(acpi_set_current_resources);
    255
    256	/* Validate the buffer, don't allow zero length */
    257
    258	if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {
    259		return_ACPI_STATUS(AE_BAD_PARAMETER);
    260	}
    261
    262	/* Validate parameters then dispatch to internal routine */
    263
    264	status = acpi_rs_validate_parameters(device_handle, in_buffer, &node);
    265	if (ACPI_FAILURE(status)) {
    266		return_ACPI_STATUS(status);
    267	}
    268
    269	status = acpi_rs_set_srs_method_data(node, in_buffer);
    270	return_ACPI_STATUS(status);
    271}
    272
    273ACPI_EXPORT_SYMBOL(acpi_set_current_resources)
    274
    275/*******************************************************************************
    276 *
    277 * FUNCTION:    acpi_get_event_resources
    278 *
    279 * PARAMETERS:  device_handle   - Handle to the device object for the
    280 *                                device we are getting resources
    281 *              in_buffer       - Pointer to a buffer containing the
    282 *                                resources to be set for the device
    283 *
    284 * RETURN:      Status
    285 *
    286 * DESCRIPTION: This function is called to get the event resources for a
    287 *              specific device. The caller must first acquire a handle for
    288 *              the desired device. The resource data is passed to the routine
    289 *              the buffer pointed to by the in_buffer variable. Uses the
    290 *              _AEI method.
    291 *
    292 ******************************************************************************/
    293acpi_status
    294acpi_get_event_resources(acpi_handle device_handle,
    295			 struct acpi_buffer *ret_buffer)
    296{
    297	acpi_status status;
    298	struct acpi_namespace_node *node;
    299
    300	ACPI_FUNCTION_TRACE(acpi_get_event_resources);
    301
    302	/* Validate parameters then dispatch to internal routine */
    303
    304	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
    305	if (ACPI_FAILURE(status)) {
    306		return_ACPI_STATUS(status);
    307	}
    308
    309	status = acpi_rs_get_aei_method_data(node, ret_buffer);
    310	return_ACPI_STATUS(status);
    311}
    312
    313ACPI_EXPORT_SYMBOL(acpi_get_event_resources)
    314
    315/******************************************************************************
    316 *
    317 * FUNCTION:    acpi_resource_to_address64
    318 *
    319 * PARAMETERS:  resource        - Pointer to a resource
    320 *              out             - Pointer to the users's return buffer
    321 *                                (a struct acpi_resource_address64)
    322 *
    323 * RETURN:      Status
    324 *
    325 * DESCRIPTION: If the resource is an address16, address32, or address64,
    326 *              copy it to the address64 return buffer. This saves the
    327 *              caller from having to duplicate code for different-sized
    328 *              addresses.
    329 *
    330 ******************************************************************************/
    331acpi_status
    332acpi_resource_to_address64(struct acpi_resource *resource,
    333			   struct acpi_resource_address64 *out)
    334{
    335	struct acpi_resource_address16 *address16;
    336	struct acpi_resource_address32 *address32;
    337
    338	if (!resource || !out) {
    339		return (AE_BAD_PARAMETER);
    340	}
    341
    342	/* Convert 16 or 32 address descriptor to 64 */
    343
    344	switch (resource->type) {
    345	case ACPI_RESOURCE_TYPE_ADDRESS16:
    346
    347		address16 =
    348		    ACPI_CAST_PTR(struct acpi_resource_address16,
    349				  &resource->data);
    350		ACPI_COPY_ADDRESS(out, address16);
    351		break;
    352
    353	case ACPI_RESOURCE_TYPE_ADDRESS32:
    354
    355		address32 =
    356		    ACPI_CAST_PTR(struct acpi_resource_address32,
    357				  &resource->data);
    358		ACPI_COPY_ADDRESS(out, address32);
    359		break;
    360
    361	case ACPI_RESOURCE_TYPE_ADDRESS64:
    362
    363		/* Simple copy for 64 bit source */
    364
    365		memcpy(out, &resource->data,
    366		       sizeof(struct acpi_resource_address64));
    367		break;
    368
    369	default:
    370
    371		return (AE_BAD_PARAMETER);
    372	}
    373
    374	return (AE_OK);
    375}
    376
    377ACPI_EXPORT_SYMBOL(acpi_resource_to_address64)
    378
    379/*******************************************************************************
    380 *
    381 * FUNCTION:    acpi_get_vendor_resource
    382 *
    383 * PARAMETERS:  device_handle   - Handle for the parent device object
    384 *              name            - Method name for the parent resource
    385 *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
    386 *              uuid            - Pointer to the UUID to be matched.
    387 *                                includes both subtype and 16-byte UUID
    388 *              ret_buffer      - Where the vendor resource is returned
    389 *
    390 * RETURN:      Status
    391 *
    392 * DESCRIPTION: Walk a resource template for the specified device to find a
    393 *              vendor-defined resource that matches the supplied UUID and
    394 *              UUID subtype. Returns a struct acpi_resource of type Vendor.
    395 *
    396 ******************************************************************************/
    397acpi_status
    398acpi_get_vendor_resource(acpi_handle device_handle,
    399			 char *name,
    400			 struct acpi_vendor_uuid *uuid,
    401			 struct acpi_buffer *ret_buffer)
    402{
    403	struct acpi_vendor_walk_info info;
    404	acpi_status status;
    405
    406	/* Other parameters are validated by acpi_walk_resources */
    407
    408	if (!uuid || !ret_buffer) {
    409		return (AE_BAD_PARAMETER);
    410	}
    411
    412	info.uuid = uuid;
    413	info.buffer = ret_buffer;
    414	info.status = AE_NOT_EXIST;
    415
    416	/* Walk the _CRS or _PRS resource list for this device */
    417
    418	status =
    419	    acpi_walk_resources(device_handle, name,
    420				acpi_rs_match_vendor_resource, &info);
    421	if (ACPI_FAILURE(status)) {
    422		return (status);
    423	}
    424
    425	return (info.status);
    426}
    427
    428ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource)
    429
    430/*******************************************************************************
    431 *
    432 * FUNCTION:    acpi_rs_match_vendor_resource
    433 *
    434 * PARAMETERS:  acpi_walk_resource_callback
    435 *
    436 * RETURN:      Status
    437 *
    438 * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID
    439 *
    440 ******************************************************************************/
    441static acpi_status
    442acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
    443{
    444	struct acpi_vendor_walk_info *info = context;
    445	struct acpi_resource_vendor_typed *vendor;
    446	struct acpi_buffer *buffer;
    447	acpi_status status;
    448
    449	/* Ignore all descriptors except Vendor */
    450
    451	if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) {
    452		return (AE_OK);
    453	}
    454
    455	vendor = &resource->data.vendor_typed;
    456
    457	/*
    458	 * For a valid match, these conditions must hold:
    459	 *
    460	 * 1) Length of descriptor data must be at least as long as a UUID struct
    461	 * 2) The UUID subtypes must match
    462	 * 3) The UUID data must match
    463	 */
    464	if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) ||
    465	    (vendor->uuid_subtype != info->uuid->subtype) ||
    466	    (memcmp(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) {
    467		return (AE_OK);
    468	}
    469
    470	/* Validate/Allocate/Clear caller buffer */
    471
    472	buffer = info->buffer;
    473	status = acpi_ut_initialize_buffer(buffer, resource->length);
    474	if (ACPI_FAILURE(status)) {
    475		return (status);
    476	}
    477
    478	/* Found the correct resource, copy and return it */
    479
    480	memcpy(buffer->pointer, resource, resource->length);
    481	buffer->length = resource->length;
    482
    483	/* Found the desired descriptor, terminate resource walk */
    484
    485	info->status = AE_OK;
    486	return (AE_CTRL_TERMINATE);
    487}
    488
    489/*******************************************************************************
    490 *
    491 * FUNCTION:    acpi_walk_resource_buffer
    492 *
    493 * PARAMETERS:  buffer          - Formatted buffer returned by one of the
    494 *                                various Get*Resource functions
    495 *              user_function   - Called for each resource
    496 *              context         - Passed to user_function
    497 *
    498 * RETURN:      Status
    499 *
    500 * DESCRIPTION: Walks the input resource template. The user_function is called
    501 *              once for each resource in the list.
    502 *
    503 ******************************************************************************/
    504
    505acpi_status
    506acpi_walk_resource_buffer(struct acpi_buffer *buffer,
    507			  acpi_walk_resource_callback user_function,
    508			  void *context)
    509{
    510	acpi_status status = AE_OK;
    511	struct acpi_resource *resource;
    512	struct acpi_resource *resource_end;
    513
    514	ACPI_FUNCTION_TRACE(acpi_walk_resource_buffer);
    515
    516	/* Parameter validation */
    517
    518	if (!buffer || !buffer->pointer || !user_function) {
    519		return_ACPI_STATUS(AE_BAD_PARAMETER);
    520	}
    521
    522	/* Buffer contains the resource list and length */
    523
    524	resource = ACPI_CAST_PTR(struct acpi_resource, buffer->pointer);
    525	resource_end =
    526	    ACPI_ADD_PTR(struct acpi_resource, buffer->pointer, buffer->length);
    527
    528	/* Walk the resource list until the end_tag is found (or buffer end) */
    529
    530	while (resource < resource_end) {
    531
    532		/* Sanity check the resource type */
    533
    534		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
    535			status = AE_AML_INVALID_RESOURCE_TYPE;
    536			break;
    537		}
    538
    539		/* Sanity check the length. It must not be zero, or we loop forever */
    540
    541		if (!resource->length) {
    542			return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
    543		}
    544
    545		/* Invoke the user function, abort on any error returned */
    546
    547		status = user_function(resource, context);
    548		if (ACPI_FAILURE(status)) {
    549			if (status == AE_CTRL_TERMINATE) {
    550
    551				/* This is an OK termination by the user function */
    552
    553				status = AE_OK;
    554			}
    555			break;
    556		}
    557
    558		/* end_tag indicates end-of-list */
    559
    560		if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
    561			break;
    562		}
    563
    564		/* Get the next resource descriptor */
    565
    566		resource = ACPI_NEXT_RESOURCE(resource);
    567	}
    568
    569	return_ACPI_STATUS(status);
    570}
    571
    572ACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer)
    573
    574/*******************************************************************************
    575 *
    576 * FUNCTION:    acpi_walk_resources
    577 *
    578 * PARAMETERS:  device_handle   - Handle to the device object for the
    579 *                                device we are querying
    580 *              name            - Method name of the resources we want.
    581 *                                (METHOD_NAME__CRS, METHOD_NAME__PRS, or
    582 *                                METHOD_NAME__AEI or METHOD_NAME__DMA)
    583 *              user_function   - Called for each resource
    584 *              context         - Passed to user_function
    585 *
    586 * RETURN:      Status
    587 *
    588 * DESCRIPTION: Retrieves the current or possible resource list for the
    589 *              specified device. The user_function is called once for
    590 *              each resource in the list.
    591 *
    592 ******************************************************************************/
    593acpi_status
    594acpi_walk_resources(acpi_handle device_handle,
    595		    char *name,
    596		    acpi_walk_resource_callback user_function, void *context)
    597{
    598	acpi_status status;
    599	struct acpi_buffer buffer;
    600
    601	ACPI_FUNCTION_TRACE(acpi_walk_resources);
    602
    603	/* Parameter validation */
    604
    605	if (!device_handle || !user_function || !name ||
    606	    (!ACPI_COMPARE_NAMESEG(name, METHOD_NAME__CRS) &&
    607	     !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__PRS) &&
    608	     !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__AEI) &&
    609	     !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__DMA))) {
    610		return_ACPI_STATUS(AE_BAD_PARAMETER);
    611	}
    612
    613	/* Get the _CRS/_PRS/_AEI/_DMA resource list */
    614
    615	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
    616	status = acpi_rs_get_method_data(device_handle, name, &buffer);
    617	if (ACPI_FAILURE(status)) {
    618		return_ACPI_STATUS(status);
    619	}
    620
    621	/* Walk the resource list and cleanup */
    622
    623	status = acpi_walk_resource_buffer(&buffer, user_function, context);
    624	ACPI_FREE(buffer.pointer);
    625	return_ACPI_STATUS(status);
    626}
    627
    628ACPI_EXPORT_SYMBOL(acpi_walk_resources)