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

excreate.c (13041B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: excreate - Named object creation
      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#include "amlcode.h"
     14#include "acnamesp.h"
     15
     16#define _COMPONENT          ACPI_EXECUTER
     17ACPI_MODULE_NAME("excreate")
     18/*******************************************************************************
     19 *
     20 * FUNCTION:    acpi_ex_create_alias
     21 *
     22 * PARAMETERS:  walk_state           - Current state, contains operands
     23 *
     24 * RETURN:      Status
     25 *
     26 * DESCRIPTION: Create a new named alias
     27 *
     28 ******************************************************************************/
     29acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
     30{
     31	struct acpi_namespace_node *target_node;
     32	struct acpi_namespace_node *alias_node;
     33	acpi_status status = AE_OK;
     34
     35	ACPI_FUNCTION_TRACE(ex_create_alias);
     36
     37	/* Get the source/alias operands (both namespace nodes) */
     38
     39	alias_node = (struct acpi_namespace_node *)walk_state->operands[0];
     40	target_node = (struct acpi_namespace_node *)walk_state->operands[1];
     41
     42	if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
     43	    (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
     44		/*
     45		 * Dereference an existing alias so that we don't create a chain
     46		 * of aliases. With this code, we guarantee that an alias is
     47		 * always exactly one level of indirection away from the
     48		 * actual aliased name.
     49		 */
     50		target_node =
     51		    ACPI_CAST_PTR(struct acpi_namespace_node,
     52				  target_node->object);
     53	}
     54
     55	/* Ensure that the target node is valid */
     56
     57	if (!target_node) {
     58		return_ACPI_STATUS(AE_NULL_OBJECT);
     59	}
     60
     61	/* Construct the alias object (a namespace node) */
     62
     63	switch (target_node->type) {
     64	case ACPI_TYPE_METHOD:
     65		/*
     66		 * Control method aliases need to be differentiated with
     67		 * a special type
     68		 */
     69		alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
     70		break;
     71
     72	default:
     73		/*
     74		 * All other object types.
     75		 *
     76		 * The new alias has the type ALIAS and points to the original
     77		 * NS node, not the object itself.
     78		 */
     79		alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
     80		alias_node->object =
     81		    ACPI_CAST_PTR(union acpi_operand_object, target_node);
     82		break;
     83	}
     84
     85	/* Since both operands are Nodes, we don't need to delete them */
     86
     87	alias_node->object =
     88	    ACPI_CAST_PTR(union acpi_operand_object, target_node);
     89	return_ACPI_STATUS(status);
     90}
     91
     92/*******************************************************************************
     93 *
     94 * FUNCTION:    acpi_ex_create_event
     95 *
     96 * PARAMETERS:  walk_state          - Current state
     97 *
     98 * RETURN:      Status
     99 *
    100 * DESCRIPTION: Create a new event object
    101 *
    102 ******************************************************************************/
    103
    104acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state)
    105{
    106	acpi_status status;
    107	union acpi_operand_object *obj_desc;
    108
    109	ACPI_FUNCTION_TRACE(ex_create_event);
    110
    111	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT);
    112	if (!obj_desc) {
    113		status = AE_NO_MEMORY;
    114		goto cleanup;
    115	}
    116
    117	/*
    118	 * Create the actual OS semaphore, with zero initial units -- meaning
    119	 * that the event is created in an unsignalled state
    120	 */
    121	status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
    122					  &obj_desc->event.os_semaphore);
    123	if (ACPI_FAILURE(status)) {
    124		goto cleanup;
    125	}
    126
    127	/* Attach object to the Node */
    128
    129	status = acpi_ns_attach_object((struct acpi_namespace_node *)
    130				       walk_state->operands[0], obj_desc,
    131				       ACPI_TYPE_EVENT);
    132
    133cleanup:
    134	/*
    135	 * Remove local reference to the object (on error, will cause deletion
    136	 * of both object and semaphore if present.)
    137	 */
    138	acpi_ut_remove_reference(obj_desc);
    139	return_ACPI_STATUS(status);
    140}
    141
    142/*******************************************************************************
    143 *
    144 * FUNCTION:    acpi_ex_create_mutex
    145 *
    146 * PARAMETERS:  walk_state          - Current state
    147 *
    148 * RETURN:      Status
    149 *
    150 * DESCRIPTION: Create a new mutex object
    151 *
    152 *              Mutex (Name[0], sync_level[1])
    153 *
    154 ******************************************************************************/
    155
    156acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
    157{
    158	acpi_status status = AE_OK;
    159	union acpi_operand_object *obj_desc;
    160
    161	ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS);
    162
    163	/* Create the new mutex object */
    164
    165	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX);
    166	if (!obj_desc) {
    167		status = AE_NO_MEMORY;
    168		goto cleanup;
    169	}
    170
    171	/* Create the actual OS Mutex */
    172
    173	status = acpi_os_create_mutex(&obj_desc->mutex.os_mutex);
    174	if (ACPI_FAILURE(status)) {
    175		goto cleanup;
    176	}
    177
    178	/* Init object and attach to NS node */
    179
    180	obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value;
    181	obj_desc->mutex.node =
    182	    (struct acpi_namespace_node *)walk_state->operands[0];
    183
    184	status =
    185	    acpi_ns_attach_object(obj_desc->mutex.node, obj_desc,
    186				  ACPI_TYPE_MUTEX);
    187
    188cleanup:
    189	/*
    190	 * Remove local reference to the object (on error, will cause deletion
    191	 * of both object and semaphore if present.)
    192	 */
    193	acpi_ut_remove_reference(obj_desc);
    194	return_ACPI_STATUS(status);
    195}
    196
    197/*******************************************************************************
    198 *
    199 * FUNCTION:    acpi_ex_create_region
    200 *
    201 * PARAMETERS:  aml_start           - Pointer to the region declaration AML
    202 *              aml_length          - Max length of the declaration AML
    203 *              space_id            - Address space ID for the region
    204 *              walk_state          - Current state
    205 *
    206 * RETURN:      Status
    207 *
    208 * DESCRIPTION: Create a new operation region object
    209 *
    210 ******************************************************************************/
    211
    212acpi_status
    213acpi_ex_create_region(u8 * aml_start,
    214		      u32 aml_length,
    215		      u8 space_id, struct acpi_walk_state *walk_state)
    216{
    217	acpi_status status;
    218	union acpi_operand_object *obj_desc;
    219	struct acpi_namespace_node *node;
    220	union acpi_operand_object *region_obj2;
    221
    222	ACPI_FUNCTION_TRACE(ex_create_region);
    223
    224	/* Get the Namespace Node */
    225
    226	node = walk_state->op->common.node;
    227
    228	/*
    229	 * If the region object is already attached to this node,
    230	 * just return
    231	 */
    232	if (acpi_ns_get_attached_object(node)) {
    233		return_ACPI_STATUS(AE_OK);
    234	}
    235
    236	/*
    237	 * Space ID must be one of the predefined IDs, or in the user-defined
    238	 * range
    239	 */
    240	if (!acpi_is_valid_space_id(space_id)) {
    241		/*
    242		 * Print an error message, but continue. We don't want to abort
    243		 * a table load for this exception. Instead, if the region is
    244		 * actually used at runtime, abort the executing method.
    245		 */
    246		ACPI_ERROR((AE_INFO,
    247			    "Invalid/unknown Address Space ID: 0x%2.2X",
    248			    space_id));
    249	}
    250
    251	ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n",
    252			  acpi_ut_get_region_name(space_id), space_id));
    253
    254	/* Create the region descriptor */
    255
    256	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
    257	if (!obj_desc) {
    258		status = AE_NO_MEMORY;
    259		goto cleanup;
    260	}
    261
    262	/*
    263	 * Remember location in AML stream of address & length
    264	 * operands since they need to be evaluated at run time.
    265	 */
    266	region_obj2 = acpi_ns_get_secondary_object(obj_desc);
    267	region_obj2->extra.aml_start = aml_start;
    268	region_obj2->extra.aml_length = aml_length;
    269	region_obj2->extra.method_REG = NULL;
    270	if (walk_state->scope_info) {
    271		region_obj2->extra.scope_node =
    272		    walk_state->scope_info->scope.node;
    273	} else {
    274		region_obj2->extra.scope_node = node;
    275	}
    276
    277	/* Init the region from the operands */
    278
    279	obj_desc->region.space_id = space_id;
    280	obj_desc->region.address = 0;
    281	obj_desc->region.length = 0;
    282	obj_desc->region.pointer = NULL;
    283	obj_desc->region.node = node;
    284	obj_desc->region.handler = NULL;
    285	obj_desc->common.flags &=
    286	    ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED |
    287	      AOPOBJ_OBJECT_INITIALIZED);
    288
    289	/* Install the new region object in the parent Node */
    290
    291	status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
    292
    293cleanup:
    294
    295	/* Remove local reference to the object */
    296
    297	acpi_ut_remove_reference(obj_desc);
    298	return_ACPI_STATUS(status);
    299}
    300
    301/*******************************************************************************
    302 *
    303 * FUNCTION:    acpi_ex_create_processor
    304 *
    305 * PARAMETERS:  walk_state          - Current state
    306 *
    307 * RETURN:      Status
    308 *
    309 * DESCRIPTION: Create a new processor object and populate the fields
    310 *
    311 *              Processor (Name[0], cpu_ID[1], pblock_addr[2], pblock_length[3])
    312 *
    313 ******************************************************************************/
    314
    315acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state)
    316{
    317	union acpi_operand_object **operand = &walk_state->operands[0];
    318	union acpi_operand_object *obj_desc;
    319	acpi_status status;
    320
    321	ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state);
    322
    323	/* Create the processor object */
    324
    325	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR);
    326	if (!obj_desc) {
    327		return_ACPI_STATUS(AE_NO_MEMORY);
    328	}
    329
    330	/* Initialize the processor object from the operands */
    331
    332	obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
    333	obj_desc->processor.length = (u8) operand[3]->integer.value;
    334	obj_desc->processor.address =
    335	    (acpi_io_address)operand[2]->integer.value;
    336
    337	/* Install the processor object in the parent Node */
    338
    339	status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
    340				       obj_desc, ACPI_TYPE_PROCESSOR);
    341
    342	/* Remove local reference to the object */
    343
    344	acpi_ut_remove_reference(obj_desc);
    345	return_ACPI_STATUS(status);
    346}
    347
    348/*******************************************************************************
    349 *
    350 * FUNCTION:    acpi_ex_create_power_resource
    351 *
    352 * PARAMETERS:  walk_state          - Current state
    353 *
    354 * RETURN:      Status
    355 *
    356 * DESCRIPTION: Create a new power_resource object and populate the fields
    357 *
    358 *              power_resource (Name[0], system_level[1], resource_order[2])
    359 *
    360 ******************************************************************************/
    361
    362acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state)
    363{
    364	union acpi_operand_object **operand = &walk_state->operands[0];
    365	acpi_status status;
    366	union acpi_operand_object *obj_desc;
    367
    368	ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state);
    369
    370	/* Create the power resource object */
    371
    372	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER);
    373	if (!obj_desc) {
    374		return_ACPI_STATUS(AE_NO_MEMORY);
    375	}
    376
    377	/* Initialize the power object from the operands */
    378
    379	obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
    380	obj_desc->power_resource.resource_order =
    381	    (u16) operand[2]->integer.value;
    382
    383	/* Install the  power resource object in the parent Node */
    384
    385	status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
    386				       obj_desc, ACPI_TYPE_POWER);
    387
    388	/* Remove local reference to the object */
    389
    390	acpi_ut_remove_reference(obj_desc);
    391	return_ACPI_STATUS(status);
    392}
    393
    394/*******************************************************************************
    395 *
    396 * FUNCTION:    acpi_ex_create_method
    397 *
    398 * PARAMETERS:  aml_start       - First byte of the method's AML
    399 *              aml_length      - AML byte count for this method
    400 *              walk_state      - Current state
    401 *
    402 * RETURN:      Status
    403 *
    404 * DESCRIPTION: Create a new method object
    405 *
    406 ******************************************************************************/
    407
    408acpi_status
    409acpi_ex_create_method(u8 * aml_start,
    410		      u32 aml_length, struct acpi_walk_state *walk_state)
    411{
    412	union acpi_operand_object **operand = &walk_state->operands[0];
    413	union acpi_operand_object *obj_desc;
    414	acpi_status status;
    415	u8 method_flags;
    416
    417	ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state);
    418
    419	/* Create a new method object */
    420
    421	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
    422	if (!obj_desc) {
    423		status = AE_NO_MEMORY;
    424		goto exit;
    425	}
    426
    427	/* Save the method's AML pointer and length  */
    428
    429	obj_desc->method.aml_start = aml_start;
    430	obj_desc->method.aml_length = aml_length;
    431	obj_desc->method.node = operand[0];
    432
    433	/*
    434	 * Disassemble the method flags. Split off the arg_count, Serialized
    435	 * flag, and sync_level for efficiency.
    436	 */
    437	method_flags = (u8)operand[1]->integer.value;
    438	obj_desc->method.param_count = (u8)
    439	    (method_flags & AML_METHOD_ARG_COUNT);
    440
    441	/*
    442	 * Get the sync_level. If method is serialized, a mutex will be
    443	 * created for this method when it is parsed.
    444	 */
    445	if (method_flags & AML_METHOD_SERIALIZED) {
    446		obj_desc->method.info_flags = ACPI_METHOD_SERIALIZED;
    447
    448		/*
    449		 * ACPI 1.0: sync_level = 0
    450		 * ACPI 2.0: sync_level = sync_level in method declaration
    451		 */
    452		obj_desc->method.sync_level = (u8)
    453		    ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
    454	}
    455
    456	/* Attach the new object to the method Node */
    457
    458	status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
    459				       obj_desc, ACPI_TYPE_METHOD);
    460
    461	/* Remove local reference to the object */
    462
    463	acpi_ut_remove_reference(obj_desc);
    464
    465exit:
    466	/* Remove a reference to the operand */
    467
    468	acpi_ut_remove_reference(operand[1]);
    469	return_ACPI_STATUS(status);
    470}