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

tbinstal.c (9387B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: tbinstal - ACPI table installation and removal
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "actables.h"
     13
     14#define _COMPONENT          ACPI_TABLES
     15ACPI_MODULE_NAME("tbinstal")
     16
     17/*******************************************************************************
     18 *
     19 * FUNCTION:    acpi_tb_install_table_with_override
     20 *
     21 * PARAMETERS:  new_table_desc          - New table descriptor to install
     22 *              override                - Whether override should be performed
     23 *              table_index             - Where the table index is returned
     24 *
     25 * RETURN:      None
     26 *
     27 * DESCRIPTION: Install an ACPI table into the global data structure. The
     28 *              table override mechanism is called to allow the host
     29 *              OS to replace any table before it is installed in the root
     30 *              table array.
     31 *
     32 ******************************************************************************/
     33void
     34acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
     35				    u8 override, u32 *table_index)
     36{
     37	u32 i;
     38	acpi_status status;
     39
     40	status = acpi_tb_get_next_table_descriptor(&i, NULL);
     41	if (ACPI_FAILURE(status)) {
     42		return;
     43	}
     44
     45	/*
     46	 * ACPI Table Override:
     47	 *
     48	 * Before we install the table, let the host OS override it with a new
     49	 * one if desired. Any table within the RSDT/XSDT can be replaced,
     50	 * including the DSDT which is pointed to by the FADT.
     51	 */
     52	if (override) {
     53		acpi_tb_override_table(new_table_desc);
     54	}
     55
     56	acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.tables[i],
     57				      new_table_desc->address,
     58				      new_table_desc->flags,
     59				      new_table_desc->pointer);
     60
     61	acpi_tb_print_table_header(new_table_desc->address,
     62				   new_table_desc->pointer);
     63
     64	/* This synchronizes acpi_gbl_dsdt_index */
     65
     66	*table_index = i;
     67
     68	/* Set the global integer width (based upon revision of the DSDT) */
     69
     70	if (i == acpi_gbl_dsdt_index) {
     71		acpi_ut_set_integer_width(new_table_desc->pointer->revision);
     72	}
     73}
     74
     75/*******************************************************************************
     76 *
     77 * FUNCTION:    acpi_tb_install_standard_table
     78 *
     79 * PARAMETERS:  address             - Address of the table (might be a virtual
     80 *                                    address depending on the table_flags)
     81 *              flags               - Flags for the table
     82 *              table               - Pointer to the table (required for virtual
     83 *                                    origins, optional for physical)
     84 *              reload              - Whether reload should be performed
     85 *              override            - Whether override should be performed
     86 *              table_index         - Where the table index is returned
     87 *
     88 * RETURN:      Status
     89 *
     90 * DESCRIPTION: This function is called to verify and install an ACPI table.
     91 *              When this function is called by "Load" or "LoadTable" opcodes,
     92 *              or by acpi_load_table() API, the "Reload" parameter is set.
     93 *              After successfully returning from this function, table is
     94 *              "INSTALLED" but not "VALIDATED".
     95 *
     96 ******************************************************************************/
     97
     98acpi_status
     99acpi_tb_install_standard_table(acpi_physical_address address,
    100			       u8 flags,
    101			       struct acpi_table_header *table,
    102			       u8 reload, u8 override, u32 *table_index)
    103{
    104	u32 i;
    105	acpi_status status = AE_OK;
    106	struct acpi_table_desc new_table_desc;
    107
    108	ACPI_FUNCTION_TRACE(tb_install_standard_table);
    109
    110	/* Acquire a temporary table descriptor for validation */
    111
    112	status =
    113	    acpi_tb_acquire_temp_table(&new_table_desc, address, flags, table);
    114	if (ACPI_FAILURE(status)) {
    115		ACPI_ERROR((AE_INFO,
    116			    "Could not acquire table length at %8.8X%8.8X",
    117			    ACPI_FORMAT_UINT64(address)));
    118		return_ACPI_STATUS(status);
    119	}
    120
    121	/*
    122	 * Optionally do not load any SSDTs from the RSDT/XSDT. This can
    123	 * be useful for debugging ACPI problems on some machines.
    124	 */
    125	if (!reload &&
    126	    acpi_gbl_disable_ssdt_table_install &&
    127	    ACPI_COMPARE_NAMESEG(&new_table_desc.signature, ACPI_SIG_SSDT)) {
    128		ACPI_INFO(("Ignoring installation of %4.4s at %8.8X%8.8X",
    129			   new_table_desc.signature.ascii,
    130			   ACPI_FORMAT_UINT64(address)));
    131		goto release_and_exit;
    132	}
    133
    134	/* Acquire the table lock */
    135
    136	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
    137
    138	/* Validate and verify a table before installation */
    139
    140	status = acpi_tb_verify_temp_table(&new_table_desc, NULL, &i);
    141	if (ACPI_FAILURE(status)) {
    142		if (status == AE_CTRL_TERMINATE) {
    143			/*
    144			 * Table was unloaded, allow it to be reloaded.
    145			 * As we are going to return AE_OK to the caller, we should
    146			 * take the responsibility of freeing the input descriptor.
    147			 * Refill the input descriptor to ensure
    148			 * acpi_tb_install_table_with_override() can be called again to
    149			 * indicate the re-installation.
    150			 */
    151			acpi_tb_uninstall_table(&new_table_desc);
    152			(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
    153			*table_index = i;
    154			return_ACPI_STATUS(AE_OK);
    155		}
    156		goto unlock_and_exit;
    157	}
    158
    159	/* Add the table to the global root table list */
    160
    161	acpi_tb_install_table_with_override(&new_table_desc, override,
    162					    table_index);
    163
    164	/* Invoke table handler */
    165
    166	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
    167	acpi_tb_notify_table(ACPI_TABLE_EVENT_INSTALL, new_table_desc.pointer);
    168	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
    169
    170unlock_and_exit:
    171
    172	/* Release the table lock */
    173
    174	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
    175
    176release_and_exit:
    177
    178	/* Release the temporary table descriptor */
    179
    180	acpi_tb_release_temp_table(&new_table_desc);
    181	return_ACPI_STATUS(status);
    182}
    183
    184/*******************************************************************************
    185 *
    186 * FUNCTION:    acpi_tb_override_table
    187 *
    188 * PARAMETERS:  old_table_desc      - Validated table descriptor to be
    189 *                                    overridden
    190 *
    191 * RETURN:      None
    192 *
    193 * DESCRIPTION: Attempt table override by calling the OSL override functions.
    194 *              Note: If the table is overridden, then the entire new table
    195 *              is acquired and returned by this function.
    196 *              Before/after invocation, the table descriptor is in a state
    197 *              that is "VALIDATED".
    198 *
    199 ******************************************************************************/
    200
    201void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
    202{
    203	acpi_status status;
    204	struct acpi_table_desc new_table_desc;
    205	struct acpi_table_header *table;
    206	acpi_physical_address address;
    207	u32 length;
    208	ACPI_ERROR_ONLY(char *override_type);
    209
    210	/* (1) Attempt logical override (returns a logical address) */
    211
    212	status = acpi_os_table_override(old_table_desc->pointer, &table);
    213	if (ACPI_SUCCESS(status) && table) {
    214		acpi_tb_acquire_temp_table(&new_table_desc,
    215					   ACPI_PTR_TO_PHYSADDR(table),
    216					   ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
    217					   table);
    218		ACPI_ERROR_ONLY(override_type = "Logical");
    219		goto finish_override;
    220	}
    221
    222	/* (2) Attempt physical override (returns a physical address) */
    223
    224	status = acpi_os_physical_table_override(old_table_desc->pointer,
    225						 &address, &length);
    226	if (ACPI_SUCCESS(status) && address && length) {
    227		acpi_tb_acquire_temp_table(&new_table_desc, address,
    228					   ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
    229					   NULL);
    230		ACPI_ERROR_ONLY(override_type = "Physical");
    231		goto finish_override;
    232	}
    233
    234	return;			/* There was no override */
    235
    236finish_override:
    237
    238	/*
    239	 * Validate and verify a table before overriding, no nested table
    240	 * duplication check as it's too complicated and unnecessary.
    241	 */
    242	status = acpi_tb_verify_temp_table(&new_table_desc, NULL, NULL);
    243	if (ACPI_FAILURE(status)) {
    244		return;
    245	}
    246
    247	ACPI_INFO(("%4.4s 0x%8.8X%8.8X"
    248		   " %s table override, new table: 0x%8.8X%8.8X",
    249		   old_table_desc->signature.ascii,
    250		   ACPI_FORMAT_UINT64(old_table_desc->address),
    251		   override_type, ACPI_FORMAT_UINT64(new_table_desc.address)));
    252
    253	/* We can now uninstall the original table */
    254
    255	acpi_tb_uninstall_table(old_table_desc);
    256
    257	/*
    258	 * Replace the original table descriptor and keep its state as
    259	 * "VALIDATED".
    260	 */
    261	acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address,
    262				      new_table_desc.flags,
    263				      new_table_desc.pointer);
    264	acpi_tb_validate_temp_table(old_table_desc);
    265
    266	/* Release the temporary table descriptor */
    267
    268	acpi_tb_release_temp_table(&new_table_desc);
    269}
    270
    271/*******************************************************************************
    272 *
    273 * FUNCTION:    acpi_tb_uninstall_table
    274 *
    275 * PARAMETERS:  table_desc          - Table descriptor
    276 *
    277 * RETURN:      None
    278 *
    279 * DESCRIPTION: Delete one internal ACPI table
    280 *
    281 ******************************************************************************/
    282
    283void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
    284{
    285
    286	ACPI_FUNCTION_TRACE(tb_uninstall_table);
    287
    288	/* Table must be installed */
    289
    290	if (!table_desc->address) {
    291		return_VOID;
    292	}
    293
    294	acpi_tb_invalidate_table(table_desc);
    295
    296	if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
    297	    ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) {
    298		ACPI_FREE(table_desc->pointer);
    299		table_desc->pointer = NULL;
    300	}
    301
    302	table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
    303	return_VOID;
    304}