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

utcache.c (6719B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: utcache - local cache allocation routines
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12
     13#define _COMPONENT          ACPI_UTILITIES
     14ACPI_MODULE_NAME("utcache")
     15
     16#ifdef ACPI_USE_LOCAL_CACHE
     17/*******************************************************************************
     18 *
     19 * FUNCTION:    acpi_os_create_cache
     20 *
     21 * PARAMETERS:  cache_name      - Ascii name for the cache
     22 *              object_size     - Size of each cached object
     23 *              max_depth       - Maximum depth of the cache (in objects)
     24 *              return_cache    - Where the new cache object is returned
     25 *
     26 * RETURN:      Status
     27 *
     28 * DESCRIPTION: Create a cache object
     29 *
     30 ******************************************************************************/
     31acpi_status
     32acpi_os_create_cache(char *cache_name,
     33		     u16 object_size,
     34		     u16 max_depth, struct acpi_memory_list **return_cache)
     35{
     36	struct acpi_memory_list *cache;
     37
     38	ACPI_FUNCTION_ENTRY();
     39
     40	if (!cache_name || !return_cache || !object_size) {
     41		return (AE_BAD_PARAMETER);
     42	}
     43
     44	/* Create the cache object */
     45
     46	cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
     47	if (!cache) {
     48		return (AE_NO_MEMORY);
     49	}
     50
     51	/* Populate the cache object and return it */
     52
     53	memset(cache, 0, sizeof(struct acpi_memory_list));
     54	cache->list_name = cache_name;
     55	cache->object_size = object_size;
     56	cache->max_depth = max_depth;
     57
     58	*return_cache = cache;
     59	return (AE_OK);
     60}
     61
     62/*******************************************************************************
     63 *
     64 * FUNCTION:    acpi_os_purge_cache
     65 *
     66 * PARAMETERS:  cache           - Handle to cache object
     67 *
     68 * RETURN:      Status
     69 *
     70 * DESCRIPTION: Free all objects within the requested cache.
     71 *
     72 ******************************************************************************/
     73
     74acpi_status acpi_os_purge_cache(struct acpi_memory_list *cache)
     75{
     76	void *next;
     77	acpi_status status;
     78
     79	ACPI_FUNCTION_ENTRY();
     80
     81	if (!cache) {
     82		return (AE_BAD_PARAMETER);
     83	}
     84
     85	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
     86	if (ACPI_FAILURE(status)) {
     87		return (status);
     88	}
     89
     90	/* Walk the list of objects in this cache */
     91
     92	while (cache->list_head) {
     93
     94		/* Delete and unlink one cached state object */
     95
     96		next = ACPI_GET_DESCRIPTOR_PTR(cache->list_head);
     97		ACPI_FREE(cache->list_head);
     98
     99		cache->list_head = next;
    100		cache->current_depth--;
    101	}
    102
    103	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
    104	return (AE_OK);
    105}
    106
    107/*******************************************************************************
    108 *
    109 * FUNCTION:    acpi_os_delete_cache
    110 *
    111 * PARAMETERS:  cache           - Handle to cache object
    112 *
    113 * RETURN:      Status
    114 *
    115 * DESCRIPTION: Free all objects within the requested cache and delete the
    116 *              cache object.
    117 *
    118 ******************************************************************************/
    119
    120acpi_status acpi_os_delete_cache(struct acpi_memory_list *cache)
    121{
    122	acpi_status status;
    123
    124	ACPI_FUNCTION_ENTRY();
    125
    126	/* Purge all objects in the cache */
    127
    128	status = acpi_os_purge_cache(cache);
    129	if (ACPI_FAILURE(status)) {
    130		return (status);
    131	}
    132
    133	/* Now we can delete the cache object */
    134
    135	acpi_os_free(cache);
    136	return (AE_OK);
    137}
    138
    139/*******************************************************************************
    140 *
    141 * FUNCTION:    acpi_os_release_object
    142 *
    143 * PARAMETERS:  cache       - Handle to cache object
    144 *              object      - The object to be released
    145 *
    146 * RETURN:      None
    147 *
    148 * DESCRIPTION: Release an object to the specified cache. If cache is full,
    149 *              the object is deleted.
    150 *
    151 ******************************************************************************/
    152
    153acpi_status acpi_os_release_object(struct acpi_memory_list *cache, void *object)
    154{
    155	acpi_status status;
    156
    157	ACPI_FUNCTION_ENTRY();
    158
    159	if (!cache || !object) {
    160		return (AE_BAD_PARAMETER);
    161	}
    162
    163	/* If cache is full, just free this object */
    164
    165	if (cache->current_depth >= cache->max_depth) {
    166		ACPI_FREE(object);
    167		ACPI_MEM_TRACKING(cache->total_freed++);
    168	}
    169
    170	/* Otherwise put this object back into the cache */
    171
    172	else {
    173		status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
    174		if (ACPI_FAILURE(status)) {
    175			return (status);
    176		}
    177
    178		/* Mark the object as cached */
    179
    180		memset(object, 0xCA, cache->object_size);
    181		ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
    182
    183		/* Put the object at the head of the cache list */
    184
    185		ACPI_SET_DESCRIPTOR_PTR(object, cache->list_head);
    186		cache->list_head = object;
    187		cache->current_depth++;
    188
    189		(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
    190	}
    191
    192	return (AE_OK);
    193}
    194
    195/*******************************************************************************
    196 *
    197 * FUNCTION:    acpi_os_acquire_object
    198 *
    199 * PARAMETERS:  cache           - Handle to cache object
    200 *
    201 * RETURN:      the acquired object. NULL on error
    202 *
    203 * DESCRIPTION: Get an object from the specified cache. If cache is empty,
    204 *              the object is allocated.
    205 *
    206 ******************************************************************************/
    207
    208void *acpi_os_acquire_object(struct acpi_memory_list *cache)
    209{
    210	acpi_status status;
    211	void *object;
    212
    213	ACPI_FUNCTION_TRACE(os_acquire_object);
    214
    215	if (!cache) {
    216		return_PTR(NULL);
    217	}
    218
    219	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
    220	if (ACPI_FAILURE(status)) {
    221		return_PTR(NULL);
    222	}
    223
    224	ACPI_MEM_TRACKING(cache->requests++);
    225
    226	/* Check the cache first */
    227
    228	if (cache->list_head) {
    229
    230		/* There is an object available, use it */
    231
    232		object = cache->list_head;
    233		cache->list_head = ACPI_GET_DESCRIPTOR_PTR(object);
    234
    235		cache->current_depth--;
    236
    237		ACPI_MEM_TRACKING(cache->hits++);
    238		ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC,
    239				      "%s: Object %p from %s cache\n",
    240				      ACPI_GET_FUNCTION_NAME, object,
    241				      cache->list_name));
    242
    243		status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
    244		if (ACPI_FAILURE(status)) {
    245			return_PTR(NULL);
    246		}
    247
    248		/* Clear (zero) the previously used Object */
    249
    250		memset(object, 0, cache->object_size);
    251	} else {
    252		/* The cache is empty, create a new object */
    253
    254		ACPI_MEM_TRACKING(cache->total_allocated++);
    255
    256#ifdef ACPI_DBG_TRACK_ALLOCATIONS
    257		if ((cache->total_allocated - cache->total_freed) >
    258		    cache->max_occupied) {
    259			cache->max_occupied =
    260			    cache->total_allocated - cache->total_freed;
    261		}
    262#endif
    263
    264		/* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
    265
    266		status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
    267		if (ACPI_FAILURE(status)) {
    268			return_PTR(NULL);
    269		}
    270
    271		object = ACPI_ALLOCATE_ZEROED(cache->object_size);
    272		if (!object) {
    273			return_PTR(NULL);
    274		}
    275	}
    276
    277	return_PTR(object);
    278}
    279#endif				/* ACPI_USE_LOCAL_CACHE */