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

evmisc.c (7262B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: evmisc - Miscellaneous event manager support functions
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acevents.h"
     13#include "acnamesp.h"
     14
     15#define _COMPONENT          ACPI_EVENTS
     16ACPI_MODULE_NAME("evmisc")
     17
     18/* Local prototypes */
     19static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
     20
     21/*******************************************************************************
     22 *
     23 * FUNCTION:    acpi_ev_is_notify_object
     24 *
     25 * PARAMETERS:  node            - Node to check
     26 *
     27 * RETURN:      TRUE if notifies allowed on this object
     28 *
     29 * DESCRIPTION: Check type of node for a object that supports notifies.
     30 *
     31 *              TBD: This could be replaced by a flag bit in the node.
     32 *
     33 ******************************************************************************/
     34
     35u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
     36{
     37
     38	switch (node->type) {
     39	case ACPI_TYPE_DEVICE:
     40	case ACPI_TYPE_PROCESSOR:
     41	case ACPI_TYPE_THERMAL:
     42		/*
     43		 * These are the ONLY objects that can receive ACPI notifications
     44		 */
     45		return (TRUE);
     46
     47	default:
     48
     49		return (FALSE);
     50	}
     51}
     52
     53/*******************************************************************************
     54 *
     55 * FUNCTION:    acpi_ev_queue_notify_request
     56 *
     57 * PARAMETERS:  node            - NS node for the notified object
     58 *              notify_value    - Value from the Notify() request
     59 *
     60 * RETURN:      Status
     61 *
     62 * DESCRIPTION: Dispatch a device notification event to a previously
     63 *              installed handler.
     64 *
     65 ******************************************************************************/
     66
     67acpi_status
     68acpi_ev_queue_notify_request(struct acpi_namespace_node *node, u32 notify_value)
     69{
     70	union acpi_operand_object *obj_desc;
     71	union acpi_operand_object *handler_list_head = NULL;
     72	union acpi_generic_state *info;
     73	u8 handler_list_id = 0;
     74	acpi_status status = AE_OK;
     75
     76	ACPI_FUNCTION_NAME(ev_queue_notify_request);
     77
     78	/* Are Notifies allowed on this object? */
     79
     80	if (!acpi_ev_is_notify_object(node)) {
     81		return (AE_TYPE);
     82	}
     83
     84	/* Get the correct notify list type (System or Device) */
     85
     86	if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
     87		handler_list_id = ACPI_SYSTEM_HANDLER_LIST;
     88	} else {
     89		handler_list_id = ACPI_DEVICE_HANDLER_LIST;
     90	}
     91
     92	/* Get the notify object attached to the namespace Node */
     93
     94	obj_desc = acpi_ns_get_attached_object(node);
     95	if (obj_desc) {
     96
     97		/* We have an attached object, Get the correct handler list */
     98
     99		handler_list_head =
    100		    obj_desc->common_notify.notify_list[handler_list_id];
    101	}
    102
    103	/*
    104	 * If there is no notify handler (Global or Local)
    105	 * for this object, just ignore the notify
    106	 */
    107	if (!acpi_gbl_global_notify[handler_list_id].handler
    108	    && !handler_list_head) {
    109		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
    110				  "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n",
    111				  acpi_ut_get_node_name(node), notify_value,
    112				  node));
    113
    114		return (AE_OK);
    115	}
    116
    117	/* Setup notify info and schedule the notify dispatcher */
    118
    119	info = acpi_ut_create_generic_state();
    120	if (!info) {
    121		return (AE_NO_MEMORY);
    122	}
    123
    124	info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY;
    125
    126	info->notify.node = node;
    127	info->notify.value = (u16)notify_value;
    128	info->notify.handler_list_id = handler_list_id;
    129	info->notify.handler_list_head = handler_list_head;
    130	info->notify.global = &acpi_gbl_global_notify[handler_list_id];
    131
    132	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
    133			  "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
    134			  acpi_ut_get_node_name(node),
    135			  acpi_ut_get_type_name(node->type), notify_value,
    136			  acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY),
    137			  node));
    138
    139	status = acpi_os_execute(OSL_NOTIFY_HANDLER,
    140				 acpi_ev_notify_dispatch, info);
    141	if (ACPI_FAILURE(status)) {
    142		acpi_ut_delete_generic_state(info);
    143	}
    144
    145	return (status);
    146}
    147
    148/*******************************************************************************
    149 *
    150 * FUNCTION:    acpi_ev_notify_dispatch
    151 *
    152 * PARAMETERS:  context         - To be passed to the notify handler
    153 *
    154 * RETURN:      None.
    155 *
    156 * DESCRIPTION: Dispatch a device notification event to a previously
    157 *              installed handler.
    158 *
    159 ******************************************************************************/
    160
    161static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
    162{
    163	union acpi_generic_state *info = (union acpi_generic_state *)context;
    164	union acpi_operand_object *handler_obj;
    165
    166	ACPI_FUNCTION_ENTRY();
    167
    168	/* Invoke a global notify handler if installed */
    169
    170	if (info->notify.global->handler) {
    171		info->notify.global->handler(info->notify.node,
    172					     info->notify.value,
    173					     info->notify.global->context);
    174	}
    175
    176	/* Now invoke the local notify handler(s) if any are installed */
    177
    178	handler_obj = info->notify.handler_list_head;
    179	while (handler_obj) {
    180		handler_obj->notify.handler(info->notify.node,
    181					    info->notify.value,
    182					    handler_obj->notify.context);
    183
    184		handler_obj =
    185		    handler_obj->notify.next[info->notify.handler_list_id];
    186	}
    187
    188	/* All done with the info object */
    189
    190	acpi_ut_delete_generic_state(info);
    191}
    192
    193#if (!ACPI_REDUCED_HARDWARE)
    194/******************************************************************************
    195 *
    196 * FUNCTION:    acpi_ev_terminate
    197 *
    198 * PARAMETERS:  none
    199 *
    200 * RETURN:      none
    201 *
    202 * DESCRIPTION: Disable events and free memory allocated for table storage.
    203 *
    204 ******************************************************************************/
    205
    206void acpi_ev_terminate(void)
    207{
    208	u32 i;
    209	acpi_status status;
    210
    211	ACPI_FUNCTION_TRACE(ev_terminate);
    212
    213	if (acpi_gbl_events_initialized) {
    214		/*
    215		 * Disable all event-related functionality. In all cases, on error,
    216		 * print a message but obviously we don't abort.
    217		 */
    218
    219		/* Disable all fixed events */
    220
    221		for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
    222			status = acpi_disable_event(i, 0);
    223			if (ACPI_FAILURE(status)) {
    224				ACPI_ERROR((AE_INFO,
    225					    "Could not disable fixed event %u",
    226					    (u32) i));
    227			}
    228		}
    229
    230		/* Disable all GPEs in all GPE blocks */
    231
    232		status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
    233		if (ACPI_FAILURE(status)) {
    234			ACPI_EXCEPTION((AE_INFO, status,
    235					"Could not disable GPEs in GPE block"));
    236		}
    237
    238		status = acpi_ev_remove_global_lock_handler();
    239		if (ACPI_FAILURE(status)) {
    240			ACPI_EXCEPTION((AE_INFO, status,
    241					"Could not remove Global Lock handler"));
    242		}
    243
    244		acpi_gbl_events_initialized = FALSE;
    245	}
    246
    247	/* Remove SCI handlers */
    248
    249	status = acpi_ev_remove_all_sci_handlers();
    250	if (ACPI_FAILURE(status)) {
    251		ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
    252	}
    253
    254	/* Deallocate all handler objects installed within GPE info structs */
    255
    256	status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL);
    257	if (ACPI_FAILURE(status)) {
    258		ACPI_EXCEPTION((AE_INFO, status,
    259				"Could not delete GPE handlers"));
    260	}
    261
    262	/* Return to original mode if necessary */
    263
    264	if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
    265		status = acpi_disable();
    266		if (ACPI_FAILURE(status)) {
    267			ACPI_WARNING((AE_INFO, "AcpiDisable failed"));
    268		}
    269	}
    270	return_VOID;
    271}
    272
    273#endif				/* !ACPI_REDUCED_HARDWARE */