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

hwesleep.c (5878B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the
      5 *                    extended FADT-V5 sleep registers.
      6 *
      7 * Copyright (C) 2000 - 2022, Intel Corp.
      8 *
      9 *****************************************************************************/
     10
     11#include <acpi/acpi.h>
     12#include "accommon.h"
     13
     14#define _COMPONENT          ACPI_HARDWARE
     15ACPI_MODULE_NAME("hwesleep")
     16
     17/*******************************************************************************
     18 *
     19 * FUNCTION:    acpi_hw_execute_sleep_method
     20 *
     21 * PARAMETERS:  method_pathname     - Pathname of method to execute
     22 *              integer_argument    - Argument to pass to the method
     23 *
     24 * RETURN:      None
     25 *
     26 * DESCRIPTION: Execute a sleep/wake related method with one integer argument
     27 *              and no return value.
     28 *
     29 ******************************************************************************/
     30void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument)
     31{
     32	struct acpi_object_list arg_list;
     33	union acpi_object arg;
     34	acpi_status status;
     35
     36	ACPI_FUNCTION_TRACE(hw_execute_sleep_method);
     37
     38	/* One argument, integer_argument; No return value expected */
     39
     40	arg_list.count = 1;
     41	arg_list.pointer = &arg;
     42	arg.type = ACPI_TYPE_INTEGER;
     43	arg.integer.value = (u64)integer_argument;
     44
     45	status = acpi_evaluate_object(NULL, method_pathname, &arg_list, NULL);
     46	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
     47		ACPI_EXCEPTION((AE_INFO, status, "While executing method %s",
     48				method_pathname));
     49	}
     50
     51	return_VOID;
     52}
     53
     54/*******************************************************************************
     55 *
     56 * FUNCTION:    acpi_hw_extended_sleep
     57 *
     58 * PARAMETERS:  sleep_state         - Which sleep state to enter
     59 *
     60 * RETURN:      Status
     61 *
     62 * DESCRIPTION: Enter a system sleep state via the extended FADT sleep
     63 *              registers (V5 FADT).
     64 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
     65 *
     66 ******************************************************************************/
     67
     68acpi_status acpi_hw_extended_sleep(u8 sleep_state)
     69{
     70	acpi_status status;
     71	u8 sleep_control;
     72	u64 sleep_status;
     73
     74	ACPI_FUNCTION_TRACE(hw_extended_sleep);
     75
     76	/* Extended sleep registers must be valid */
     77
     78	if (!acpi_gbl_FADT.sleep_control.address ||
     79	    !acpi_gbl_FADT.sleep_status.address) {
     80		return_ACPI_STATUS(AE_NOT_EXIST);
     81	}
     82
     83	/* Clear wake status (WAK_STS) */
     84
     85	status = acpi_write((u64)ACPI_X_WAKE_STATUS,
     86			    &acpi_gbl_FADT.sleep_status);
     87	if (ACPI_FAILURE(status)) {
     88		return_ACPI_STATUS(status);
     89	}
     90
     91	acpi_gbl_system_awake_and_running = FALSE;
     92
     93	/*
     94	 * Set the SLP_TYP and SLP_EN bits.
     95	 *
     96	 * Note: We only use the first value returned by the \_Sx method
     97	 * (acpi_gbl_sleep_type_a) - As per ACPI specification.
     98	 */
     99	ACPI_DEBUG_PRINT((ACPI_DB_INIT,
    100			  "Entering sleep state [S%u]\n", sleep_state));
    101
    102	sleep_control = ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
    103			 ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE;
    104
    105	/* Flush caches, as per ACPI specification */
    106
    107	if (sleep_state < ACPI_STATE_S4) {
    108		ACPI_FLUSH_CPU_CACHE();
    109	}
    110
    111	status = acpi_os_enter_sleep(sleep_state, sleep_control, 0);
    112	if (status == AE_CTRL_TERMINATE) {
    113		return_ACPI_STATUS(AE_OK);
    114	}
    115	if (ACPI_FAILURE(status)) {
    116		return_ACPI_STATUS(status);
    117	}
    118
    119	status = acpi_write((u64)sleep_control, &acpi_gbl_FADT.sleep_control);
    120	if (ACPI_FAILURE(status)) {
    121		return_ACPI_STATUS(status);
    122	}
    123
    124	/* Wait for transition back to Working State */
    125
    126	do {
    127		status = acpi_read(&sleep_status, &acpi_gbl_FADT.sleep_status);
    128		if (ACPI_FAILURE(status)) {
    129			return_ACPI_STATUS(status);
    130		}
    131
    132	} while (!(((u8)sleep_status) & ACPI_X_WAKE_STATUS));
    133
    134	return_ACPI_STATUS(AE_OK);
    135}
    136
    137/*******************************************************************************
    138 *
    139 * FUNCTION:    acpi_hw_extended_wake_prep
    140 *
    141 * PARAMETERS:  sleep_state         - Which sleep state we just exited
    142 *
    143 * RETURN:      Status
    144 *
    145 * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after
    146 *              a sleep. Called with interrupts ENABLED.
    147 *
    148 ******************************************************************************/
    149
    150acpi_status acpi_hw_extended_wake_prep(u8 sleep_state)
    151{
    152	u8 sleep_type_value;
    153
    154	ACPI_FUNCTION_TRACE(hw_extended_wake_prep);
    155
    156	if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) {
    157		sleep_type_value =
    158		    ((acpi_gbl_sleep_type_a_s0 << ACPI_X_SLEEP_TYPE_POSITION) &
    159		     ACPI_X_SLEEP_TYPE_MASK);
    160
    161		(void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE),
    162				 &acpi_gbl_FADT.sleep_control);
    163	}
    164
    165	return_ACPI_STATUS(AE_OK);
    166}
    167
    168/*******************************************************************************
    169 *
    170 * FUNCTION:    acpi_hw_extended_wake
    171 *
    172 * PARAMETERS:  sleep_state         - Which sleep state we just exited
    173 *
    174 * RETURN:      Status
    175 *
    176 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
    177 *              Called with interrupts ENABLED.
    178 *
    179 ******************************************************************************/
    180
    181acpi_status acpi_hw_extended_wake(u8 sleep_state)
    182{
    183	ACPI_FUNCTION_TRACE(hw_extended_wake);
    184
    185	/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
    186
    187	acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
    188
    189	/* Execute the wake methods */
    190
    191	acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING);
    192	acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state);
    193
    194	/*
    195	 * Some BIOS code assumes that WAK_STS will be cleared on resume
    196	 * and use it to determine whether the system is rebooting or
    197	 * resuming. Clear WAK_STS for compatibility.
    198	 */
    199	(void)acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
    200	acpi_gbl_system_awake_and_running = TRUE;
    201
    202	acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
    203	return_ACPI_STATUS(AE_OK);
    204}