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

nsalloc.c (12715B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/*******************************************************************************
      3 *
      4 * Module Name: nsalloc - Namespace allocation and deletion utilities
      5 *
      6 ******************************************************************************/
      7
      8#include <acpi/acpi.h>
      9#include "accommon.h"
     10#include "acnamesp.h"
     11
     12#define _COMPONENT          ACPI_NAMESPACE
     13ACPI_MODULE_NAME("nsalloc")
     14
     15/*******************************************************************************
     16 *
     17 * FUNCTION:    acpi_ns_create_node
     18 *
     19 * PARAMETERS:  name            - Name of the new node (4 char ACPI name)
     20 *
     21 * RETURN:      New namespace node (Null on failure)
     22 *
     23 * DESCRIPTION: Create a namespace node
     24 *
     25 ******************************************************************************/
     26struct acpi_namespace_node *acpi_ns_create_node(u32 name)
     27{
     28	struct acpi_namespace_node *node;
     29#ifdef ACPI_DBG_TRACK_ALLOCATIONS
     30	u32 temp;
     31#endif
     32
     33	ACPI_FUNCTION_TRACE(ns_create_node);
     34
     35	node = acpi_os_acquire_object(acpi_gbl_namespace_cache);
     36	if (!node) {
     37		return_PTR(NULL);
     38	}
     39
     40	ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++);
     41
     42#ifdef ACPI_DBG_TRACK_ALLOCATIONS
     43	temp = acpi_gbl_ns_node_list->total_allocated -
     44	    acpi_gbl_ns_node_list->total_freed;
     45	if (temp > acpi_gbl_ns_node_list->max_occupied) {
     46		acpi_gbl_ns_node_list->max_occupied = temp;
     47	}
     48#endif
     49
     50	node->name.integer = name;
     51	ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED);
     52	return_PTR(node);
     53}
     54
     55/*******************************************************************************
     56 *
     57 * FUNCTION:    acpi_ns_delete_node
     58 *
     59 * PARAMETERS:  node            - Node to be deleted
     60 *
     61 * RETURN:      None
     62 *
     63 * DESCRIPTION: Delete a namespace node. All node deletions must come through
     64 *              here. Detaches any attached objects, including any attached
     65 *              data. If a handler is associated with attached data, it is
     66 *              invoked before the node is deleted.
     67 *
     68 ******************************************************************************/
     69
     70void acpi_ns_delete_node(struct acpi_namespace_node *node)
     71{
     72	union acpi_operand_object *obj_desc;
     73	union acpi_operand_object *next_desc;
     74
     75	ACPI_FUNCTION_NAME(ns_delete_node);
     76
     77	if (!node) {
     78		return_VOID;
     79	}
     80
     81	/* Detach an object if there is one */
     82
     83	acpi_ns_detach_object(node);
     84
     85	/*
     86	 * Delete an attached data object list if present (objects that were
     87	 * attached via acpi_attach_data). Note: After any normal object is
     88	 * detached above, the only possible remaining object(s) are data
     89	 * objects, in a linked list.
     90	 */
     91	obj_desc = node->object;
     92	while (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
     93
     94		/* Invoke the attached data deletion handler if present */
     95
     96		if (obj_desc->data.handler) {
     97			obj_desc->data.handler(node, obj_desc->data.pointer);
     98		}
     99
    100		next_desc = obj_desc->common.next_object;
    101		acpi_ut_remove_reference(obj_desc);
    102		obj_desc = next_desc;
    103	}
    104
    105	/* Special case for the statically allocated root node */
    106
    107	if (node == acpi_gbl_root_node) {
    108		return;
    109	}
    110
    111	/* Now we can delete the node */
    112
    113	(void)acpi_os_release_object(acpi_gbl_namespace_cache, node);
    114
    115	ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
    116	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n",
    117			  node, acpi_gbl_current_node_count));
    118}
    119
    120/*******************************************************************************
    121 *
    122 * FUNCTION:    acpi_ns_remove_node
    123 *
    124 * PARAMETERS:  node            - Node to be removed/deleted
    125 *
    126 * RETURN:      None
    127 *
    128 * DESCRIPTION: Remove (unlink) and delete a namespace node
    129 *
    130 ******************************************************************************/
    131
    132void acpi_ns_remove_node(struct acpi_namespace_node *node)
    133{
    134	struct acpi_namespace_node *parent_node;
    135	struct acpi_namespace_node *prev_node;
    136	struct acpi_namespace_node *next_node;
    137
    138	ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node);
    139
    140	parent_node = node->parent;
    141
    142	prev_node = NULL;
    143	next_node = parent_node->child;
    144
    145	/* Find the node that is the previous peer in the parent's child list */
    146
    147	while (next_node != node) {
    148		prev_node = next_node;
    149		next_node = next_node->peer;
    150	}
    151
    152	if (prev_node) {
    153
    154		/* Node is not first child, unlink it */
    155
    156		prev_node->peer = node->peer;
    157	} else {
    158		/*
    159		 * Node is first child (has no previous peer).
    160		 * Link peer list to parent
    161		 */
    162		parent_node->child = node->peer;
    163	}
    164
    165	/* Delete the node and any attached objects */
    166
    167	acpi_ns_delete_node(node);
    168	return_VOID;
    169}
    170
    171/*******************************************************************************
    172 *
    173 * FUNCTION:    acpi_ns_install_node
    174 *
    175 * PARAMETERS:  walk_state      - Current state of the walk
    176 *              parent_node     - The parent of the new Node
    177 *              node            - The new Node to install
    178 *              type            - ACPI object type of the new Node
    179 *
    180 * RETURN:      None
    181 *
    182 * DESCRIPTION: Initialize a new namespace node and install it amongst
    183 *              its peers.
    184 *
    185 *              Note: Current namespace lookup is linear search. This appears
    186 *              to be sufficient as namespace searches consume only a small
    187 *              fraction of the execution time of the ACPI subsystem.
    188 *
    189 ******************************************************************************/
    190
    191void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parent_node,	/* Parent */
    192			  struct acpi_namespace_node *node,	/* New Child */
    193			  acpi_object_type type)
    194{
    195	acpi_owner_id owner_id = 0;
    196	struct acpi_namespace_node *child_node;
    197
    198	ACPI_FUNCTION_TRACE(ns_install_node);
    199
    200	if (walk_state) {
    201		/*
    202		 * Get the owner ID from the Walk state. The owner ID is used to
    203		 * track table deletion and deletion of objects created by methods.
    204		 */
    205		owner_id = walk_state->owner_id;
    206
    207		if ((walk_state->method_desc) &&
    208		    (parent_node != walk_state->method_node)) {
    209			/*
    210			 * A method is creating a new node that is not a child of the
    211			 * method (it is non-local). Mark the executing method as having
    212			 * modified the namespace. This is used for cleanup when the
    213			 * method exits.
    214			 */
    215			walk_state->method_desc->method.info_flags |=
    216			    ACPI_METHOD_MODIFIED_NAMESPACE;
    217		}
    218	}
    219
    220	/* Link the new entry into the parent and existing children */
    221
    222	node->peer = NULL;
    223	node->parent = parent_node;
    224	child_node = parent_node->child;
    225
    226	if (!child_node) {
    227		parent_node->child = node;
    228	} else {
    229		/* Add node to the end of the peer list */
    230
    231		while (child_node->peer) {
    232			child_node = child_node->peer;
    233		}
    234
    235		child_node->peer = node;
    236	}
    237
    238	/* Init the new entry */
    239
    240	node->owner_id = owner_id;
    241	node->type = (u8) type;
    242
    243	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
    244			  "%4.4s (%s) [Node %p Owner %3.3X] added to %4.4s (%s) [Node %p]\n",
    245			  acpi_ut_get_node_name(node),
    246			  acpi_ut_get_type_name(node->type), node, owner_id,
    247			  acpi_ut_get_node_name(parent_node),
    248			  acpi_ut_get_type_name(parent_node->type),
    249			  parent_node));
    250
    251	return_VOID;
    252}
    253
    254/*******************************************************************************
    255 *
    256 * FUNCTION:    acpi_ns_delete_children
    257 *
    258 * PARAMETERS:  parent_node     - Delete this objects children
    259 *
    260 * RETURN:      None.
    261 *
    262 * DESCRIPTION: Delete all children of the parent object. In other words,
    263 *              deletes a "scope".
    264 *
    265 ******************************************************************************/
    266
    267void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
    268{
    269	struct acpi_namespace_node *next_node;
    270	struct acpi_namespace_node *node_to_delete;
    271
    272	ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node);
    273
    274	if (!parent_node) {
    275		return_VOID;
    276	}
    277
    278	/* Deallocate all children at this level */
    279
    280	next_node = parent_node->child;
    281	while (next_node) {
    282
    283		/* Grandchildren should have all been deleted already */
    284
    285		if (next_node->child) {
    286			ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p",
    287				    parent_node, next_node));
    288		}
    289
    290		/*
    291		 * Delete this child node and move on to the next child in the list.
    292		 * No need to unlink the node since we are deleting the entire branch.
    293		 */
    294		node_to_delete = next_node;
    295		next_node = next_node->peer;
    296		acpi_ns_delete_node(node_to_delete);
    297	}
    298
    299	/* Clear the parent's child pointer */
    300
    301	parent_node->child = NULL;
    302	return_VOID;
    303}
    304
    305/*******************************************************************************
    306 *
    307 * FUNCTION:    acpi_ns_delete_namespace_subtree
    308 *
    309 * PARAMETERS:  parent_node     - Root of the subtree to be deleted
    310 *
    311 * RETURN:      None.
    312 *
    313 * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
    314 *              stored within the subtree.
    315 *
    316 ******************************************************************************/
    317
    318void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
    319{
    320	struct acpi_namespace_node *child_node = NULL;
    321	u32 level = 1;
    322	acpi_status status;
    323
    324	ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree);
    325
    326	if (!parent_node) {
    327		return_VOID;
    328	}
    329
    330	/* Lock namespace for possible update */
    331
    332	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
    333	if (ACPI_FAILURE(status)) {
    334		return_VOID;
    335	}
    336
    337	/*
    338	 * Traverse the tree of objects until we bubble back up
    339	 * to where we started.
    340	 */
    341	while (level > 0) {
    342
    343		/* Get the next node in this scope (NULL if none) */
    344
    345		child_node = acpi_ns_get_next_node(parent_node, child_node);
    346		if (child_node) {
    347
    348			/* Found a child node - detach any attached object */
    349
    350			acpi_ns_detach_object(child_node);
    351
    352			/* Check if this node has any children */
    353
    354			if (child_node->child) {
    355				/*
    356				 * There is at least one child of this node,
    357				 * visit the node
    358				 */
    359				level++;
    360				parent_node = child_node;
    361				child_node = NULL;
    362			}
    363		} else {
    364			/*
    365			 * No more children of this parent node.
    366			 * Move up to the grandparent.
    367			 */
    368			level--;
    369
    370			/*
    371			 * Now delete all of the children of this parent
    372			 * all at the same time.
    373			 */
    374			acpi_ns_delete_children(parent_node);
    375
    376			/* New "last child" is this parent node */
    377
    378			child_node = parent_node;
    379
    380			/* Move up the tree to the grandparent */
    381
    382			parent_node = parent_node->parent;
    383		}
    384	}
    385
    386	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
    387	return_VOID;
    388}
    389
    390/*******************************************************************************
    391 *
    392 * FUNCTION:    acpi_ns_delete_namespace_by_owner
    393 *
    394 * PARAMETERS:  owner_id    - All nodes with this owner will be deleted
    395 *
    396 * RETURN:      Status
    397 *
    398 * DESCRIPTION: Delete entries within the namespace that are owned by a
    399 *              specific ID. Used to delete entire ACPI tables. All
    400 *              reference counts are updated.
    401 *
    402 * MUTEX:       Locks namespace during deletion walk.
    403 *
    404 ******************************************************************************/
    405
    406void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
    407{
    408	struct acpi_namespace_node *child_node;
    409	struct acpi_namespace_node *deletion_node;
    410	struct acpi_namespace_node *parent_node;
    411	u32 level;
    412	acpi_status status;
    413
    414	ACPI_FUNCTION_TRACE_U32(ns_delete_namespace_by_owner, owner_id);
    415
    416	if (owner_id == 0) {
    417		return_VOID;
    418	}
    419
    420	/* Lock namespace for possible update */
    421
    422	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
    423	if (ACPI_FAILURE(status)) {
    424		return_VOID;
    425	}
    426
    427	deletion_node = NULL;
    428	parent_node = acpi_gbl_root_node;
    429	child_node = NULL;
    430	level = 1;
    431
    432	/*
    433	 * Traverse the tree of nodes until we bubble back up
    434	 * to where we started.
    435	 */
    436	while (level > 0) {
    437		/*
    438		 * Get the next child of this parent node. When child_node is NULL,
    439		 * the first child of the parent is returned
    440		 */
    441		child_node = acpi_ns_get_next_node(parent_node, child_node);
    442
    443		if (deletion_node) {
    444			acpi_ns_delete_children(deletion_node);
    445			acpi_ns_remove_node(deletion_node);
    446			deletion_node = NULL;
    447		}
    448
    449		if (child_node) {
    450			if (child_node->owner_id == owner_id) {
    451
    452				/* Found a matching child node - detach any attached object */
    453
    454				acpi_ns_detach_object(child_node);
    455			}
    456
    457			/* Check if this node has any children */
    458
    459			if (child_node->child) {
    460				/*
    461				 * There is at least one child of this node,
    462				 * visit the node
    463				 */
    464				level++;
    465				parent_node = child_node;
    466				child_node = NULL;
    467			} else if (child_node->owner_id == owner_id) {
    468				deletion_node = child_node;
    469			}
    470		} else {
    471			/*
    472			 * No more children of this parent node.
    473			 * Move up to the grandparent.
    474			 */
    475			level--;
    476			if (level != 0) {
    477				if (parent_node->owner_id == owner_id) {
    478					deletion_node = parent_node;
    479				}
    480			}
    481
    482			/* New "last child" is this parent node */
    483
    484			child_node = parent_node;
    485
    486			/* Move up the tree to the grandparent */
    487
    488			parent_node = parent_node->parent;
    489		}
    490	}
    491
    492	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
    493	return_VOID;
    494}