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

psxface.c (9478B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: psxface - Parser external interfaces
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acparser.h"
     13#include "acdispat.h"
     14#include "acinterp.h"
     15#include "actables.h"
     16#include "acnamesp.h"
     17
     18#define _COMPONENT          ACPI_PARSER
     19ACPI_MODULE_NAME("psxface")
     20
     21/* Local Prototypes */
     22static void
     23acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
     24
     25/*******************************************************************************
     26 *
     27 * FUNCTION:    acpi_debug_trace
     28 *
     29 * PARAMETERS:  method_name     - Valid ACPI name string
     30 *              debug_level     - Optional level mask. 0 to use default
     31 *              debug_layer     - Optional layer mask. 0 to use default
     32 *              flags           - bit 1: one shot(1) or persistent(0)
     33 *
     34 * RETURN:      Status
     35 *
     36 * DESCRIPTION: External interface to enable debug tracing during control
     37 *              method execution
     38 *
     39 ******************************************************************************/
     40
     41acpi_status
     42acpi_debug_trace(const char *name, u32 debug_level, u32 debug_layer, u32 flags)
     43{
     44	acpi_status status;
     45
     46	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     47	if (ACPI_FAILURE(status)) {
     48		return (status);
     49	}
     50
     51	acpi_gbl_trace_method_name = name;
     52	acpi_gbl_trace_flags = flags;
     53	acpi_gbl_trace_dbg_level = debug_level;
     54	acpi_gbl_trace_dbg_layer = debug_layer;
     55	status = AE_OK;
     56
     57	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     58	return (status);
     59}
     60
     61/*******************************************************************************
     62 *
     63 * FUNCTION:    acpi_ps_execute_method
     64 *
     65 * PARAMETERS:  info            - Method info block, contains:
     66 *                  node            - Method Node to execute
     67 *                  obj_desc        - Method object
     68 *                  parameters      - List of parameters to pass to the method,
     69 *                                    terminated by NULL. Params itself may be
     70 *                                    NULL if no parameters are being passed.
     71 *                  return_object   - Where to put method's return value (if
     72 *                                    any). If NULL, no value is returned.
     73 *                  parameter_type  - Type of Parameter list
     74 *                  return_object   - Where to put method's return value (if
     75 *                                    any). If NULL, no value is returned.
     76 *                  pass_number     - Parse or execute pass
     77 *
     78 * RETURN:      Status
     79 *
     80 * DESCRIPTION: Execute a control method
     81 *
     82 ******************************************************************************/
     83
     84acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
     85{
     86	acpi_status status;
     87	union acpi_parse_object *op;
     88	struct acpi_walk_state *walk_state;
     89
     90	ACPI_FUNCTION_TRACE(ps_execute_method);
     91
     92	/* Quick validation of DSDT header */
     93
     94	acpi_tb_check_dsdt_header();
     95
     96	/* Validate the Info and method Node */
     97
     98	if (!info || !info->node) {
     99		return_ACPI_STATUS(AE_NULL_ENTRY);
    100	}
    101
    102	/* Init for new method, wait on concurrency semaphore */
    103
    104	status =
    105	    acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL);
    106	if (ACPI_FAILURE(status)) {
    107		return_ACPI_STATUS(status);
    108	}
    109
    110	/*
    111	 * The caller "owns" the parameters, so give each one an extra reference
    112	 */
    113	acpi_ps_update_parameter_list(info, REF_INCREMENT);
    114
    115	/*
    116	 * Execute the method. Performs parse simultaneously
    117	 */
    118	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
    119			  "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n",
    120			  info->node->name.ascii, info->node, info->obj_desc));
    121
    122	/* Create and init a Root Node */
    123
    124	op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
    125	if (!op) {
    126		status = AE_NO_MEMORY;
    127		goto cleanup;
    128	}
    129
    130	/* Create and initialize a new walk state */
    131
    132	info->pass_number = ACPI_IMODE_EXECUTE;
    133	walk_state =
    134	    acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
    135				      NULL, NULL);
    136	if (!walk_state) {
    137		status = AE_NO_MEMORY;
    138		goto cleanup;
    139	}
    140
    141	status = acpi_ds_init_aml_walk(walk_state, op, info->node,
    142				       info->obj_desc->method.aml_start,
    143				       info->obj_desc->method.aml_length, info,
    144				       info->pass_number);
    145	if (ACPI_FAILURE(status)) {
    146		acpi_ds_delete_walk_state(walk_state);
    147		goto cleanup;
    148	}
    149
    150	walk_state->method_pathname = info->full_pathname;
    151	walk_state->method_is_nested = FALSE;
    152
    153	if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
    154		walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
    155	}
    156
    157	/* Invoke an internal method if necessary */
    158
    159	if (info->obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
    160		status =
    161		    info->obj_desc->method.dispatch.implementation(walk_state);
    162		info->return_object = walk_state->return_desc;
    163
    164		/* Cleanup states */
    165
    166		acpi_ds_scope_stack_clear(walk_state);
    167		acpi_ps_cleanup_scope(&walk_state->parser_state);
    168		acpi_ds_terminate_control_method(walk_state->method_desc,
    169						 walk_state);
    170		acpi_ds_delete_walk_state(walk_state);
    171		goto cleanup;
    172	}
    173
    174	/*
    175	 * Start method evaluation with an implicit return of zero.
    176	 * This is done for Windows compatibility.
    177	 */
    178	if (acpi_gbl_enable_interpreter_slack) {
    179		walk_state->implicit_return_obj =
    180		    acpi_ut_create_integer_object((u64) 0);
    181		if (!walk_state->implicit_return_obj) {
    182			status = AE_NO_MEMORY;
    183			acpi_ds_delete_walk_state(walk_state);
    184			goto cleanup;
    185		}
    186	}
    187
    188	/* Parse the AML */
    189
    190	status = acpi_ps_parse_aml(walk_state);
    191
    192	/* walk_state was deleted by parse_aml */
    193
    194cleanup:
    195	acpi_ps_delete_parse_tree(op);
    196
    197	/* Take away the extra reference that we gave the parameters above */
    198
    199	acpi_ps_update_parameter_list(info, REF_DECREMENT);
    200
    201	/* Exit now if error above */
    202
    203	if (ACPI_FAILURE(status)) {
    204		return_ACPI_STATUS(status);
    205	}
    206
    207	/*
    208	 * If the method has returned an object, signal this to the caller with
    209	 * a control exception code
    210	 */
    211	if (info->return_object) {
    212		ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
    213				  info->return_object));
    214		ACPI_DUMP_STACK_ENTRY(info->return_object);
    215
    216		status = AE_CTRL_RETURN_VALUE;
    217	}
    218
    219	return_ACPI_STATUS(status);
    220}
    221
    222/*******************************************************************************
    223 *
    224 * FUNCTION:    acpi_ps_execute_table
    225 *
    226 * PARAMETERS:  info            - Method info block, contains:
    227 *              node            - Node to where the is entered into the
    228 *                                namespace
    229 *              obj_desc        - Pseudo method object describing the AML
    230 *                                code of the entire table
    231 *              pass_number     - Parse or execute pass
    232 *
    233 * RETURN:      Status
    234 *
    235 * DESCRIPTION: Execute a table
    236 *
    237 ******************************************************************************/
    238
    239acpi_status acpi_ps_execute_table(struct acpi_evaluate_info *info)
    240{
    241	acpi_status status;
    242	union acpi_parse_object *op = NULL;
    243	struct acpi_walk_state *walk_state = NULL;
    244
    245	ACPI_FUNCTION_TRACE(ps_execute_table);
    246
    247	/* Create and init a Root Node */
    248
    249	op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
    250	if (!op) {
    251		status = AE_NO_MEMORY;
    252		goto cleanup;
    253	}
    254
    255	/* Create and initialize a new walk state */
    256
    257	walk_state =
    258	    acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
    259				      NULL, NULL);
    260	if (!walk_state) {
    261		status = AE_NO_MEMORY;
    262		goto cleanup;
    263	}
    264
    265	status = acpi_ds_init_aml_walk(walk_state, op, info->node,
    266				       info->obj_desc->method.aml_start,
    267				       info->obj_desc->method.aml_length, info,
    268				       info->pass_number);
    269	if (ACPI_FAILURE(status)) {
    270		goto cleanup;
    271	}
    272
    273	walk_state->method_pathname = info->full_pathname;
    274	walk_state->method_is_nested = FALSE;
    275
    276	if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
    277		walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
    278	}
    279
    280	/* Info->Node is the default location to load the table  */
    281
    282	if (info->node && info->node != acpi_gbl_root_node) {
    283		status =
    284		    acpi_ds_scope_stack_push(info->node, ACPI_TYPE_METHOD,
    285					     walk_state);
    286		if (ACPI_FAILURE(status)) {
    287			goto cleanup;
    288		}
    289	}
    290
    291	/*
    292	 * Parse the AML, walk_state will be deleted by parse_aml
    293	 */
    294	acpi_ex_enter_interpreter();
    295	status = acpi_ps_parse_aml(walk_state);
    296	acpi_ex_exit_interpreter();
    297	walk_state = NULL;
    298
    299cleanup:
    300	if (walk_state) {
    301		acpi_ds_delete_walk_state(walk_state);
    302	}
    303	if (op) {
    304		acpi_ps_delete_parse_tree(op);
    305	}
    306	return_ACPI_STATUS(status);
    307}
    308
    309/*******************************************************************************
    310 *
    311 * FUNCTION:    acpi_ps_update_parameter_list
    312 *
    313 * PARAMETERS:  info            - See struct acpi_evaluate_info
    314 *                                (Used: parameter_type and Parameters)
    315 *              action          - Add or Remove reference
    316 *
    317 * RETURN:      Status
    318 *
    319 * DESCRIPTION: Update reference count on all method parameter objects
    320 *
    321 ******************************************************************************/
    322
    323static void
    324acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
    325{
    326	u32 i;
    327
    328	if (info->parameters) {
    329
    330		/* Update reference count for each parameter */
    331
    332		for (i = 0; info->parameters[i]; i++) {
    333
    334			/* Ignore errors, just do them all */
    335
    336			(void)acpi_ut_update_object_reference(info->
    337							      parameters[i],
    338							      action);
    339		}
    340	}
    341}