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

tbxface.c (15465B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: tbxface - ACPI table-oriented external interfaces
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#define EXPORT_ACPI_INTERFACES
     11
     12#include <acpi/acpi.h>
     13#include "accommon.h"
     14#include "actables.h"
     15
     16#define _COMPONENT          ACPI_TABLES
     17ACPI_MODULE_NAME("tbxface")
     18
     19/*******************************************************************************
     20 *
     21 * FUNCTION:    acpi_allocate_root_table
     22 *
     23 * PARAMETERS:  initial_table_count - Size of initial_table_array, in number of
     24 *                                    struct acpi_table_desc structures
     25 *
     26 * RETURN:      Status
     27 *
     28 * DESCRIPTION: Allocate a root table array. Used by iASL compiler and
     29 *              acpi_initialize_tables.
     30 *
     31 ******************************************************************************/
     32acpi_status acpi_allocate_root_table(u32 initial_table_count)
     33{
     34
     35	acpi_gbl_root_table_list.max_table_count = initial_table_count;
     36	acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE;
     37
     38	return (acpi_tb_resize_root_table_list());
     39}
     40
     41/*******************************************************************************
     42 *
     43 * FUNCTION:    acpi_initialize_tables
     44 *
     45 * PARAMETERS:  initial_table_array - Pointer to an array of pre-allocated
     46 *                                    struct acpi_table_desc structures. If NULL, the
     47 *                                    array is dynamically allocated.
     48 *              initial_table_count - Size of initial_table_array, in number of
     49 *                                    struct acpi_table_desc structures
     50 *              allow_resize        - Flag to tell Table Manager if resize of
     51 *                                    pre-allocated array is allowed. Ignored
     52 *                                    if initial_table_array is NULL.
     53 *
     54 * RETURN:      Status
     55 *
     56 * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT.
     57 *
     58 * NOTE:        Allows static allocation of the initial table array in order
     59 *              to avoid the use of dynamic memory in confined environments
     60 *              such as the kernel boot sequence where it may not be available.
     61 *
     62 *              If the host OS memory managers are initialized, use NULL for
     63 *              initial_table_array, and the table will be dynamically allocated.
     64 *
     65 ******************************************************************************/
     66
     67acpi_status ACPI_INIT_FUNCTION
     68acpi_initialize_tables(struct acpi_table_desc *initial_table_array,
     69		       u32 initial_table_count, u8 allow_resize)
     70{
     71	acpi_physical_address rsdp_address;
     72	acpi_status status;
     73
     74	ACPI_FUNCTION_TRACE(acpi_initialize_tables);
     75
     76	/*
     77	 * Setup the Root Table Array and allocate the table array
     78	 * if requested
     79	 */
     80	if (!initial_table_array) {
     81		status = acpi_allocate_root_table(initial_table_count);
     82		if (ACPI_FAILURE(status)) {
     83			return_ACPI_STATUS(status);
     84		}
     85	} else {
     86		/* Root Table Array has been statically allocated by the host */
     87
     88		memset(initial_table_array, 0,
     89		       (acpi_size)initial_table_count *
     90		       sizeof(struct acpi_table_desc));
     91
     92		acpi_gbl_root_table_list.tables = initial_table_array;
     93		acpi_gbl_root_table_list.max_table_count = initial_table_count;
     94		acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
     95		if (allow_resize) {
     96			acpi_gbl_root_table_list.flags |=
     97			    ACPI_ROOT_ALLOW_RESIZE;
     98		}
     99	}
    100
    101	/* Get the address of the RSDP */
    102
    103	rsdp_address = acpi_os_get_root_pointer();
    104	if (!rsdp_address) {
    105		return_ACPI_STATUS(AE_NOT_FOUND);
    106	}
    107
    108	/*
    109	 * Get the root table (RSDT or XSDT) and extract all entries to the local
    110	 * Root Table Array. This array contains the information of the RSDT/XSDT
    111	 * in a common, more usable format.
    112	 */
    113	status = acpi_tb_parse_root_table(rsdp_address);
    114	return_ACPI_STATUS(status);
    115}
    116
    117ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables)
    118
    119/*******************************************************************************
    120 *
    121 * FUNCTION:    acpi_reallocate_root_table
    122 *
    123 * PARAMETERS:  None
    124 *
    125 * RETURN:      Status
    126 *
    127 * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the
    128 *              root list from the previously provided scratch area. Should
    129 *              be called once dynamic memory allocation is available in the
    130 *              kernel.
    131 *
    132 ******************************************************************************/
    133acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void)
    134{
    135	acpi_status status;
    136	struct acpi_table_desc *table_desc;
    137	u32 i, j;
    138
    139	ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
    140
    141	/*
    142	 * If there are tables unverified, it is required to reallocate the
    143	 * root table list to clean up invalid table entries. Otherwise only
    144	 * reallocate the root table list if the host provided a static buffer
    145	 * for the table array in the call to acpi_initialize_tables().
    146	 */
    147	if ((acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) &&
    148	    acpi_gbl_enable_table_validation) {
    149		return_ACPI_STATUS(AE_SUPPORT);
    150	}
    151
    152	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
    153
    154	/*
    155	 * Ensure OS early boot logic, which is required by some hosts. If the
    156	 * table state is reported to be wrong, developers should fix the
    157	 * issue by invoking acpi_put_table() for the reported table during the
    158	 * early stage.
    159	 */
    160	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
    161		table_desc = &acpi_gbl_root_table_list.tables[i];
    162		if (table_desc->pointer) {
    163			ACPI_ERROR((AE_INFO,
    164				    "Table [%4.4s] is not invalidated during early boot stage",
    165				    table_desc->signature.ascii));
    166		}
    167	}
    168
    169	if (!acpi_gbl_enable_table_validation) {
    170		/*
    171		 * Now it's safe to do full table validation. We can do deferred
    172		 * table initialization here once the flag is set.
    173		 */
    174		acpi_gbl_enable_table_validation = TRUE;
    175		for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
    176		     ++i) {
    177			table_desc = &acpi_gbl_root_table_list.tables[i];
    178			if (!(table_desc->flags & ACPI_TABLE_IS_VERIFIED)) {
    179				status =
    180				    acpi_tb_verify_temp_table(table_desc, NULL,
    181							      &j);
    182				if (ACPI_FAILURE(status)) {
    183					acpi_tb_uninstall_table(table_desc);
    184				}
    185			}
    186		}
    187	}
    188
    189	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE;
    190	status = acpi_tb_resize_root_table_list();
    191	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
    192
    193	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
    194	return_ACPI_STATUS(status);
    195}
    196
    197ACPI_EXPORT_SYMBOL_INIT(acpi_reallocate_root_table)
    198
    199/*******************************************************************************
    200 *
    201 * FUNCTION:    acpi_get_table_header
    202 *
    203 * PARAMETERS:  signature           - ACPI signature of needed table
    204 *              instance            - Which instance (for SSDTs)
    205 *              out_table_header    - The pointer to the where the table header
    206 *                                    is returned
    207 *
    208 * RETURN:      Status and a copy of the table header
    209 *
    210 * DESCRIPTION: Finds and returns an ACPI table header. Caller provides the
    211 *              memory where a copy of the header is to be returned
    212 *              (fixed length).
    213 *
    214 ******************************************************************************/
    215acpi_status
    216acpi_get_table_header(char *signature,
    217		      u32 instance, struct acpi_table_header *out_table_header)
    218{
    219	u32 i;
    220	u32 j;
    221	struct acpi_table_header *header;
    222
    223	/* Parameter validation */
    224
    225	if (!signature || !out_table_header) {
    226		return (AE_BAD_PARAMETER);
    227	}
    228
    229	/* Walk the root table list */
    230
    231	for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
    232	     i++) {
    233		if (!ACPI_COMPARE_NAMESEG
    234		    (&(acpi_gbl_root_table_list.tables[i].signature),
    235		     signature)) {
    236			continue;
    237		}
    238
    239		if (++j < instance) {
    240			continue;
    241		}
    242
    243		if (!acpi_gbl_root_table_list.tables[i].pointer) {
    244			if ((acpi_gbl_root_table_list.tables[i].flags &
    245			     ACPI_TABLE_ORIGIN_MASK) ==
    246			    ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) {
    247				header =
    248				    acpi_os_map_memory(acpi_gbl_root_table_list.
    249						       tables[i].address,
    250						       sizeof(struct
    251							      acpi_table_header));
    252				if (!header) {
    253					return (AE_NO_MEMORY);
    254				}
    255
    256				memcpy(out_table_header, header,
    257				       sizeof(struct acpi_table_header));
    258				acpi_os_unmap_memory(header,
    259						     sizeof(struct
    260							    acpi_table_header));
    261			} else {
    262				return (AE_NOT_FOUND);
    263			}
    264		} else {
    265			memcpy(out_table_header,
    266			       acpi_gbl_root_table_list.tables[i].pointer,
    267			       sizeof(struct acpi_table_header));
    268		}
    269		return (AE_OK);
    270	}
    271
    272	return (AE_NOT_FOUND);
    273}
    274
    275ACPI_EXPORT_SYMBOL(acpi_get_table_header)
    276
    277/*******************************************************************************
    278 *
    279 * FUNCTION:    acpi_get_table
    280 *
    281 * PARAMETERS:  signature           - ACPI signature of needed table
    282 *              instance            - Which instance (for SSDTs)
    283 *              out_table           - Where the pointer to the table is returned
    284 *
    285 * RETURN:      Status and pointer to the requested table
    286 *
    287 * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
    288 *              RSDT/XSDT.
    289 *              Note that an early stage acpi_get_table() call must be paired
    290 *              with an early stage acpi_put_table() call. otherwise the table
    291 *              pointer mapped by the early stage mapping implementation may be
    292 *              erroneously unmapped by the late stage unmapping implementation
    293 *              in an acpi_put_table() invoked during the late stage.
    294 *
    295 ******************************************************************************/
    296acpi_status
    297acpi_get_table(char *signature,
    298	       u32 instance, struct acpi_table_header ** out_table)
    299{
    300	u32 i;
    301	u32 j;
    302	acpi_status status = AE_NOT_FOUND;
    303	struct acpi_table_desc *table_desc;
    304
    305	/* Parameter validation */
    306
    307	if (!signature || !out_table) {
    308		return (AE_BAD_PARAMETER);
    309	}
    310
    311	/*
    312	 * Note that the following line is required by some OSPMs, they only
    313	 * check if the returned table is NULL instead of the returned status
    314	 * to determined if this function is succeeded.
    315	 */
    316	*out_table = NULL;
    317
    318	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
    319
    320	/* Walk the root table list */
    321
    322	for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
    323	     i++) {
    324		table_desc = &acpi_gbl_root_table_list.tables[i];
    325
    326		if (!ACPI_COMPARE_NAMESEG(&table_desc->signature, signature)) {
    327			continue;
    328		}
    329
    330		if (++j < instance) {
    331			continue;
    332		}
    333
    334		status = acpi_tb_get_table(table_desc, out_table);
    335		break;
    336	}
    337
    338	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
    339	return (status);
    340}
    341
    342ACPI_EXPORT_SYMBOL(acpi_get_table)
    343
    344/*******************************************************************************
    345 *
    346 * FUNCTION:    acpi_put_table
    347 *
    348 * PARAMETERS:  table               - The pointer to the table
    349 *
    350 * RETURN:      None
    351 *
    352 * DESCRIPTION: Release a table returned by acpi_get_table() and its clones.
    353 *              Note that it is not safe if this function was invoked after an
    354 *              uninstallation happened to the original table descriptor.
    355 *              Currently there is no OSPMs' requirement to handle such
    356 *              situations.
    357 *
    358 ******************************************************************************/
    359void acpi_put_table(struct acpi_table_header *table)
    360{
    361	u32 i;
    362	struct acpi_table_desc *table_desc;
    363
    364	ACPI_FUNCTION_TRACE(acpi_put_table);
    365
    366	if (!table) {
    367		return_VOID;
    368	}
    369
    370	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
    371
    372	/* Walk the root table list */
    373
    374	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
    375		table_desc = &acpi_gbl_root_table_list.tables[i];
    376
    377		if (table_desc->pointer != table) {
    378			continue;
    379		}
    380
    381		acpi_tb_put_table(table_desc);
    382		break;
    383	}
    384
    385	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
    386	return_VOID;
    387}
    388
    389ACPI_EXPORT_SYMBOL(acpi_put_table)
    390
    391/*******************************************************************************
    392 *
    393 * FUNCTION:    acpi_get_table_by_index
    394 *
    395 * PARAMETERS:  table_index         - Table index
    396 *              out_table           - Where the pointer to the table is returned
    397 *
    398 * RETURN:      Status and pointer to the requested table
    399 *
    400 * DESCRIPTION: Obtain a table by an index into the global table list. Used
    401 *              internally also.
    402 *
    403 ******************************************************************************/
    404acpi_status
    405acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table)
    406{
    407	acpi_status status;
    408
    409	ACPI_FUNCTION_TRACE(acpi_get_table_by_index);
    410
    411	/* Parameter validation */
    412
    413	if (!out_table) {
    414		return_ACPI_STATUS(AE_BAD_PARAMETER);
    415	}
    416
    417	/*
    418	 * Note that the following line is required by some OSPMs, they only
    419	 * check if the returned table is NULL instead of the returned status
    420	 * to determined if this function is succeeded.
    421	 */
    422	*out_table = NULL;
    423
    424	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
    425
    426	/* Validate index */
    427
    428	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
    429		status = AE_BAD_PARAMETER;
    430		goto unlock_and_exit;
    431	}
    432
    433	status =
    434	    acpi_tb_get_table(&acpi_gbl_root_table_list.tables[table_index],
    435			      out_table);
    436
    437unlock_and_exit:
    438	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
    439	return_ACPI_STATUS(status);
    440}
    441
    442ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
    443
    444/*******************************************************************************
    445 *
    446 * FUNCTION:    acpi_install_table_handler
    447 *
    448 * PARAMETERS:  handler         - Table event handler
    449 *              context         - Value passed to the handler on each event
    450 *
    451 * RETURN:      Status
    452 *
    453 * DESCRIPTION: Install a global table event handler.
    454 *
    455 ******************************************************************************/
    456acpi_status
    457acpi_install_table_handler(acpi_table_handler handler, void *context)
    458{
    459	acpi_status status;
    460
    461	ACPI_FUNCTION_TRACE(acpi_install_table_handler);
    462
    463	if (!handler) {
    464		return_ACPI_STATUS(AE_BAD_PARAMETER);
    465	}
    466
    467	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
    468	if (ACPI_FAILURE(status)) {
    469		return_ACPI_STATUS(status);
    470	}
    471
    472	/* Don't allow more than one handler */
    473
    474	if (acpi_gbl_table_handler) {
    475		status = AE_ALREADY_EXISTS;
    476		goto cleanup;
    477	}
    478
    479	/* Install the handler */
    480
    481	acpi_gbl_table_handler = handler;
    482	acpi_gbl_table_handler_context = context;
    483
    484cleanup:
    485	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
    486	return_ACPI_STATUS(status);
    487}
    488
    489ACPI_EXPORT_SYMBOL(acpi_install_table_handler)
    490
    491/*******************************************************************************
    492 *
    493 * FUNCTION:    acpi_remove_table_handler
    494 *
    495 * PARAMETERS:  handler         - Table event handler that was installed
    496 *                                previously.
    497 *
    498 * RETURN:      Status
    499 *
    500 * DESCRIPTION: Remove a table event handler
    501 *
    502 ******************************************************************************/
    503acpi_status acpi_remove_table_handler(acpi_table_handler handler)
    504{
    505	acpi_status status;
    506
    507	ACPI_FUNCTION_TRACE(acpi_remove_table_handler);
    508
    509	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
    510	if (ACPI_FAILURE(status)) {
    511		return_ACPI_STATUS(status);
    512	}
    513
    514	/* Make sure that the installed handler is the same */
    515
    516	if (!handler || handler != acpi_gbl_table_handler) {
    517		status = AE_BAD_PARAMETER;
    518		goto cleanup;
    519	}
    520
    521	/* Remove the handler */
    522
    523	acpi_gbl_table_handler = NULL;
    524
    525cleanup:
    526	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
    527	return_ACPI_STATUS(status);
    528}
    529
    530ACPI_EXPORT_SYMBOL(acpi_remove_table_handler)