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

exoparg2.c (14360B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
      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 "acinterp.h"
     14#include "acevents.h"
     15#include "amlcode.h"
     16
     17#define _COMPONENT          ACPI_EXECUTER
     18ACPI_MODULE_NAME("exoparg2")
     19
     20/*!
     21 * Naming convention for AML interpreter execution routines.
     22 *
     23 * The routines that begin execution of AML opcodes are named with a common
     24 * convention based upon the number of arguments, the number of target operands,
     25 * and whether or not a value is returned:
     26 *
     27 *      AcpiExOpcode_xA_yT_zR
     28 *
     29 * Where:
     30 *
     31 * xA - ARGUMENTS:    The number of arguments (input operands) that are
     32 *                    required for this opcode type (1 through 6 args).
     33 * yT - TARGETS:      The number of targets (output operands) that are required
     34 *                    for this opcode type (0, 1, or 2 targets).
     35 * zR - RETURN VALUE: Indicates whether this opcode type returns a value
     36 *                    as the function return (0 or 1).
     37 *
     38 * The AcpiExOpcode* functions are called via the Dispatcher component with
     39 * fully resolved operands.
     40!*/
     41/*******************************************************************************
     42 *
     43 * FUNCTION:    acpi_ex_opcode_2A_0T_0R
     44 *
     45 * PARAMETERS:  walk_state          - Current walk state
     46 *
     47 * RETURN:      Status
     48 *
     49 * DESCRIPTION: Execute opcode with two arguments, no target, and no return
     50 *              value.
     51 *
     52 * ALLOCATION:  Deletes both operands
     53 *
     54 ******************************************************************************/
     55acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
     56{
     57	union acpi_operand_object **operand = &walk_state->operands[0];
     58	struct acpi_namespace_node *node;
     59	u32 value;
     60	acpi_status status = AE_OK;
     61
     62	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R,
     63				acpi_ps_get_opcode_name(walk_state->opcode));
     64
     65	/* Examine the opcode */
     66
     67	switch (walk_state->opcode) {
     68	case AML_NOTIFY_OP:	/* Notify (notify_object, notify_value) */
     69
     70		/* The first operand is a namespace node */
     71
     72		node = (struct acpi_namespace_node *)operand[0];
     73
     74		/* Second value is the notify value */
     75
     76		value = (u32) operand[1]->integer.value;
     77
     78		/* Are notifies allowed on this object? */
     79
     80		if (!acpi_ev_is_notify_object(node)) {
     81			ACPI_ERROR((AE_INFO,
     82				    "Unexpected notify object type [%s]",
     83				    acpi_ut_get_type_name(node->type)));
     84
     85			status = AE_AML_OPERAND_TYPE;
     86			break;
     87		}
     88
     89		/*
     90		 * Dispatch the notify to the appropriate handler
     91		 * NOTE: the request is queued for execution after this method
     92		 * completes. The notify handlers are NOT invoked synchronously
     93		 * from this thread -- because handlers may in turn run other
     94		 * control methods.
     95		 */
     96		status = acpi_ev_queue_notify_request(node, value);
     97		break;
     98
     99	default:
    100
    101		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
    102			    walk_state->opcode));
    103		status = AE_AML_BAD_OPCODE;
    104	}
    105
    106	return_ACPI_STATUS(status);
    107}
    108
    109/*******************************************************************************
    110 *
    111 * FUNCTION:    acpi_ex_opcode_2A_2T_1R
    112 *
    113 * PARAMETERS:  walk_state          - Current walk state
    114 *
    115 * RETURN:      Status
    116 *
    117 * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
    118 *              and one implicit return value.
    119 *
    120 ******************************************************************************/
    121
    122acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
    123{
    124	union acpi_operand_object **operand = &walk_state->operands[0];
    125	union acpi_operand_object *return_desc1 = NULL;
    126	union acpi_operand_object *return_desc2 = NULL;
    127	acpi_status status;
    128
    129	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R,
    130				acpi_ps_get_opcode_name(walk_state->opcode));
    131
    132	/* Execute the opcode */
    133
    134	switch (walk_state->opcode) {
    135	case AML_DIVIDE_OP:
    136
    137		/* Divide (Dividend, Divisor, remainder_result quotient_result) */
    138
    139		return_desc1 =
    140		    acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
    141		if (!return_desc1) {
    142			status = AE_NO_MEMORY;
    143			goto cleanup;
    144		}
    145
    146		return_desc2 =
    147		    acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
    148		if (!return_desc2) {
    149			status = AE_NO_MEMORY;
    150			goto cleanup;
    151		}
    152
    153		/* Quotient to return_desc1, remainder to return_desc2 */
    154
    155		status = acpi_ut_divide(operand[0]->integer.value,
    156					operand[1]->integer.value,
    157					&return_desc1->integer.value,
    158					&return_desc2->integer.value);
    159		if (ACPI_FAILURE(status)) {
    160			goto cleanup;
    161		}
    162		break;
    163
    164	default:
    165
    166		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
    167			    walk_state->opcode));
    168
    169		status = AE_AML_BAD_OPCODE;
    170		goto cleanup;
    171	}
    172
    173	/* Store the results to the target reference operands */
    174
    175	status = acpi_ex_store(return_desc2, operand[2], walk_state);
    176	if (ACPI_FAILURE(status)) {
    177		goto cleanup;
    178	}
    179
    180	status = acpi_ex_store(return_desc1, operand[3], walk_state);
    181	if (ACPI_FAILURE(status)) {
    182		goto cleanup;
    183	}
    184
    185cleanup:
    186	/*
    187	 * Since the remainder is not returned indirectly, remove a reference to
    188	 * it. Only the quotient is returned indirectly.
    189	 */
    190	acpi_ut_remove_reference(return_desc2);
    191
    192	if (ACPI_FAILURE(status)) {
    193
    194		/* Delete the return object */
    195
    196		acpi_ut_remove_reference(return_desc1);
    197	}
    198
    199	/* Save return object (the remainder) on success */
    200
    201	else {
    202		walk_state->result_obj = return_desc1;
    203	}
    204
    205	return_ACPI_STATUS(status);
    206}
    207
    208/*******************************************************************************
    209 *
    210 * FUNCTION:    acpi_ex_opcode_2A_1T_1R
    211 *
    212 * PARAMETERS:  walk_state          - Current walk state
    213 *
    214 * RETURN:      Status
    215 *
    216 * DESCRIPTION: Execute opcode with two arguments, one target, and a return
    217 *              value.
    218 *
    219 ******************************************************************************/
    220
    221acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
    222{
    223	union acpi_operand_object **operand = &walk_state->operands[0];
    224	union acpi_operand_object *return_desc = NULL;
    225	u64 index;
    226	acpi_status status = AE_OK;
    227	acpi_size length = 0;
    228
    229	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R,
    230				acpi_ps_get_opcode_name(walk_state->opcode));
    231
    232	/* Execute the opcode */
    233
    234	if (walk_state->op_info->flags & AML_MATH) {
    235
    236		/* All simple math opcodes (add, etc.) */
    237
    238		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
    239		if (!return_desc) {
    240			status = AE_NO_MEMORY;
    241			goto cleanup;
    242		}
    243
    244		return_desc->integer.value =
    245		    acpi_ex_do_math_op(walk_state->opcode,
    246				       operand[0]->integer.value,
    247				       operand[1]->integer.value);
    248		goto store_result_to_target;
    249	}
    250
    251	switch (walk_state->opcode) {
    252	case AML_MOD_OP:	/* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
    253
    254		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
    255		if (!return_desc) {
    256			status = AE_NO_MEMORY;
    257			goto cleanup;
    258		}
    259
    260		/* return_desc will contain the remainder */
    261
    262		status = acpi_ut_divide(operand[0]->integer.value,
    263					operand[1]->integer.value,
    264					NULL, &return_desc->integer.value);
    265		break;
    266
    267	case AML_CONCATENATE_OP:	/* Concatenate (Data1, Data2, Result) */
    268
    269		status =
    270		    acpi_ex_do_concatenate(operand[0], operand[1], &return_desc,
    271					   walk_state);
    272		break;
    273
    274	case AML_TO_STRING_OP:	/* to_string (Buffer, Length, Result) (ACPI 2.0) */
    275		/*
    276		 * Input object is guaranteed to be a buffer at this point (it may have
    277		 * been converted.)  Copy the raw buffer data to a new object of
    278		 * type String.
    279		 */
    280
    281		/*
    282		 * Get the length of the new string. It is the smallest of:
    283		 * 1) Length of the input buffer
    284		 * 2) Max length as specified in the to_string operator
    285		 * 3) Length of input buffer up to a zero byte (null terminator)
    286		 *
    287		 * NOTE: A length of zero is ok, and will create a zero-length, null
    288		 *       terminated string.
    289		 */
    290		while ((length < operand[0]->buffer.length) &&	/* Length of input buffer */
    291		       (length < operand[1]->integer.value) &&	/* Length operand */
    292		       (operand[0]->buffer.pointer[length])) {	/* Null terminator */
    293			length++;
    294		}
    295
    296		/* Allocate a new string object */
    297
    298		return_desc = acpi_ut_create_string_object(length);
    299		if (!return_desc) {
    300			status = AE_NO_MEMORY;
    301			goto cleanup;
    302		}
    303
    304		/*
    305		 * Copy the raw buffer data with no transform.
    306		 * (NULL terminated already)
    307		 */
    308		memcpy(return_desc->string.pointer,
    309		       operand[0]->buffer.pointer, length);
    310		break;
    311
    312	case AML_CONCATENATE_TEMPLATE_OP:
    313
    314		/* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
    315
    316		status =
    317		    acpi_ex_concat_template(operand[0], operand[1],
    318					    &return_desc, walk_state);
    319		break;
    320
    321	case AML_INDEX_OP:	/* Index (Source Index Result) */
    322
    323		/* Create the internal return object */
    324
    325		return_desc =
    326		    acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
    327		if (!return_desc) {
    328			status = AE_NO_MEMORY;
    329			goto cleanup;
    330		}
    331
    332		/* Initialize the Index reference object */
    333
    334		index = operand[1]->integer.value;
    335		return_desc->reference.value = (u32) index;
    336		return_desc->reference.class = ACPI_REFCLASS_INDEX;
    337
    338		/*
    339		 * At this point, the Source operand is a String, Buffer, or Package.
    340		 * Verify that the index is within range.
    341		 */
    342		switch ((operand[0])->common.type) {
    343		case ACPI_TYPE_STRING:
    344
    345			if (index >= operand[0]->string.length) {
    346				length = operand[0]->string.length;
    347				status = AE_AML_STRING_LIMIT;
    348			}
    349
    350			return_desc->reference.target_type =
    351			    ACPI_TYPE_BUFFER_FIELD;
    352			return_desc->reference.index_pointer =
    353			    &(operand[0]->buffer.pointer[index]);
    354			break;
    355
    356		case ACPI_TYPE_BUFFER:
    357
    358			if (index >= operand[0]->buffer.length) {
    359				length = operand[0]->buffer.length;
    360				status = AE_AML_BUFFER_LIMIT;
    361			}
    362
    363			return_desc->reference.target_type =
    364			    ACPI_TYPE_BUFFER_FIELD;
    365			return_desc->reference.index_pointer =
    366			    &(operand[0]->buffer.pointer[index]);
    367			break;
    368
    369		case ACPI_TYPE_PACKAGE:
    370
    371			if (index >= operand[0]->package.count) {
    372				length = operand[0]->package.count;
    373				status = AE_AML_PACKAGE_LIMIT;
    374			}
    375
    376			return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
    377			return_desc->reference.where =
    378			    &operand[0]->package.elements[index];
    379			break;
    380
    381		default:
    382
    383			ACPI_ERROR((AE_INFO,
    384				    "Invalid object type: %X",
    385				    (operand[0])->common.type));
    386			status = AE_AML_INTERNAL;
    387			goto cleanup;
    388		}
    389
    390		/* Failure means that the Index was beyond the end of the object */
    391
    392		if (ACPI_FAILURE(status)) {
    393			ACPI_BIOS_EXCEPTION((AE_INFO, status,
    394					     "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
    395					     ACPI_FORMAT_UINT64(index),
    396					     (u32)length));
    397			goto cleanup;
    398		}
    399
    400		/*
    401		 * Save the target object and add a reference to it for the life
    402		 * of the index
    403		 */
    404		return_desc->reference.object = operand[0];
    405		acpi_ut_add_reference(operand[0]);
    406
    407		/* Store the reference to the Target */
    408
    409		status = acpi_ex_store(return_desc, operand[2], walk_state);
    410
    411		/* Return the reference */
    412
    413		walk_state->result_obj = return_desc;
    414		goto cleanup;
    415
    416	default:
    417
    418		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
    419			    walk_state->opcode));
    420		status = AE_AML_BAD_OPCODE;
    421		break;
    422	}
    423
    424store_result_to_target:
    425
    426	if (ACPI_SUCCESS(status)) {
    427		/*
    428		 * Store the result of the operation (which is now in return_desc) into
    429		 * the Target descriptor.
    430		 */
    431		status = acpi_ex_store(return_desc, operand[2], walk_state);
    432		if (ACPI_FAILURE(status)) {
    433			goto cleanup;
    434		}
    435
    436		if (!walk_state->result_obj) {
    437			walk_state->result_obj = return_desc;
    438		}
    439	}
    440
    441cleanup:
    442
    443	/* Delete return object on error */
    444
    445	if (ACPI_FAILURE(status)) {
    446		acpi_ut_remove_reference(return_desc);
    447		walk_state->result_obj = NULL;
    448	}
    449
    450	return_ACPI_STATUS(status);
    451}
    452
    453/*******************************************************************************
    454 *
    455 * FUNCTION:    acpi_ex_opcode_2A_0T_1R
    456 *
    457 * PARAMETERS:  walk_state          - Current walk state
    458 *
    459 * RETURN:      Status
    460 *
    461 * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
    462 *
    463 ******************************************************************************/
    464
    465acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
    466{
    467	union acpi_operand_object **operand = &walk_state->operands[0];
    468	union acpi_operand_object *return_desc = NULL;
    469	acpi_status status = AE_OK;
    470	u8 logical_result = FALSE;
    471
    472	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R,
    473				acpi_ps_get_opcode_name(walk_state->opcode));
    474
    475	/* Create the internal return object */
    476
    477	return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
    478	if (!return_desc) {
    479		status = AE_NO_MEMORY;
    480		goto cleanup;
    481	}
    482
    483	/* Execute the Opcode */
    484
    485	if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
    486
    487		/* logical_op (Operand0, Operand1) */
    488
    489		status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
    490						       operand[0]->integer.
    491						       value,
    492						       operand[1]->integer.
    493						       value, &logical_result);
    494		goto store_logical_result;
    495	} else if (walk_state->op_info->flags & AML_LOGICAL) {
    496
    497		/* logical_op (Operand0, Operand1) */
    498
    499		status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
    500					       operand[1], &logical_result);
    501		goto store_logical_result;
    502	}
    503
    504	switch (walk_state->opcode) {
    505	case AML_ACQUIRE_OP:	/* Acquire (mutex_object, Timeout) */
    506
    507		status =
    508		    acpi_ex_acquire_mutex(operand[1], operand[0], walk_state);
    509		if (status == AE_TIME) {
    510			logical_result = TRUE;	/* TRUE = Acquire timed out */
    511			status = AE_OK;
    512		}
    513		break;
    514
    515	case AML_WAIT_OP:	/* Wait (event_object, Timeout) */
    516
    517		status = acpi_ex_system_wait_event(operand[1], operand[0]);
    518		if (status == AE_TIME) {
    519			logical_result = TRUE;	/* TRUE, Wait timed out */
    520			status = AE_OK;
    521		}
    522		break;
    523
    524	default:
    525
    526		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
    527			    walk_state->opcode));
    528
    529		status = AE_AML_BAD_OPCODE;
    530		goto cleanup;
    531	}
    532
    533store_logical_result:
    534	/*
    535	 * Set return value to according to logical_result. logical TRUE (all ones)
    536	 * Default is FALSE (zero)
    537	 */
    538	if (logical_result) {
    539		return_desc->integer.value = ACPI_UINT64_MAX;
    540	}
    541
    542cleanup:
    543
    544	/* Delete return object on error */
    545
    546	if (ACPI_FAILURE(status)) {
    547		acpi_ut_remove_reference(return_desc);
    548	}
    549
    550	/* Save return object on success */
    551
    552	else {
    553		walk_state->result_obj = return_desc;
    554	}
    555
    556	return_ACPI_STATUS(status);
    557}