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

hwgpe.c (18406B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: hwgpe - Low level GPE enable/disable/clear 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
     14#define _COMPONENT          ACPI_HARDWARE
     15ACPI_MODULE_NAME("hwgpe")
     16#if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
     17/* Local prototypes */
     18static acpi_status
     19acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
     20				struct acpi_gpe_block_info *gpe_block,
     21				void *context);
     22
     23static acpi_status
     24acpi_hw_gpe_enable_write(u8 enable_mask,
     25			 struct acpi_gpe_register_info *gpe_register_info);
     26
     27/******************************************************************************
     28 *
     29 * FUNCTION:    acpi_hw_gpe_read
     30 *
     31 * PARAMETERS:  value               - Where the value is returned
     32 *              reg                 - GPE register structure
     33 *
     34 * RETURN:      Status
     35 *
     36 * DESCRIPTION: Read from a GPE register in either memory or IO space.
     37 *
     38 * LIMITATIONS: <These limitations also apply to acpi_hw_gpe_write>
     39 *      space_ID must be system_memory or system_IO.
     40 *
     41 ******************************************************************************/
     42
     43acpi_status acpi_hw_gpe_read(u64 *value, struct acpi_gpe_address *reg)
     44{
     45	acpi_status status;
     46	u32 value32;
     47
     48	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
     49#ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES
     50		*value = (u64)ACPI_GET8((unsigned long)reg->address);
     51		return_ACPI_STATUS(AE_OK);
     52#else
     53		return acpi_os_read_memory((acpi_physical_address)reg->address,
     54					    value, ACPI_GPE_REGISTER_WIDTH);
     55#endif
     56	}
     57
     58	status = acpi_os_read_port((acpi_io_address)reg->address,
     59				   &value32, ACPI_GPE_REGISTER_WIDTH);
     60	if (ACPI_FAILURE(status))
     61		return_ACPI_STATUS(status);
     62
     63	*value = (u64)value32;
     64
     65	return_ACPI_STATUS(AE_OK);
     66}
     67
     68/******************************************************************************
     69 *
     70 * FUNCTION:    acpi_hw_gpe_write
     71 *
     72 * PARAMETERS:  value               - Value to be written
     73 *              reg                 - GPE register structure
     74 *
     75 * RETURN:      Status
     76 *
     77 * DESCRIPTION: Write to a GPE register in either memory or IO space.
     78 *
     79 ******************************************************************************/
     80
     81acpi_status acpi_hw_gpe_write(u64 value, struct acpi_gpe_address *reg)
     82{
     83	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
     84#ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES
     85		ACPI_SET8((unsigned long)reg->address, value);
     86		return_ACPI_STATUS(AE_OK);
     87#else
     88		return acpi_os_write_memory((acpi_physical_address)reg->address,
     89					    value, ACPI_GPE_REGISTER_WIDTH);
     90#endif
     91	}
     92
     93	return acpi_os_write_port((acpi_io_address)reg->address, (u32)value,
     94				  ACPI_GPE_REGISTER_WIDTH);
     95}
     96
     97/******************************************************************************
     98 *
     99 * FUNCTION:	acpi_hw_get_gpe_register_bit
    100 *
    101 * PARAMETERS:	gpe_event_info	    - Info block for the GPE
    102 *
    103 * RETURN:	Register mask with a one in the GPE bit position
    104 *
    105 * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
    106 *              correct position for the input GPE.
    107 *
    108 ******************************************************************************/
    109
    110u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
    111{
    112
    113	return ((u32)1 <<
    114		(gpe_event_info->gpe_number -
    115		 gpe_event_info->register_info->base_gpe_number));
    116}
    117
    118/******************************************************************************
    119 *
    120 * FUNCTION:	acpi_hw_low_set_gpe
    121 *
    122 * PARAMETERS:	gpe_event_info	    - Info block for the GPE to be disabled
    123 *		action		    - Enable or disable
    124 *
    125 * RETURN:	Status
    126 *
    127 * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
    128 *              The enable_mask field of the involved GPE register must be
    129 *              updated by the caller if necessary.
    130 *
    131 ******************************************************************************/
    132
    133acpi_status
    134acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
    135{
    136	struct acpi_gpe_register_info *gpe_register_info;
    137	acpi_status status = AE_OK;
    138	u64 enable_mask;
    139	u32 register_bit;
    140
    141	ACPI_FUNCTION_ENTRY();
    142
    143	/* Get the info block for the entire GPE register */
    144
    145	gpe_register_info = gpe_event_info->register_info;
    146	if (!gpe_register_info) {
    147		return (AE_NOT_EXIST);
    148	}
    149
    150	/* Get current value of the enable register that contains this GPE */
    151
    152	status = acpi_hw_gpe_read(&enable_mask,
    153				  &gpe_register_info->enable_address);
    154	if (ACPI_FAILURE(status)) {
    155		return (status);
    156	}
    157
    158	/* Set or clear just the bit that corresponds to this GPE */
    159
    160	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
    161	switch (action) {
    162	case ACPI_GPE_CONDITIONAL_ENABLE:
    163
    164		/* Only enable if the corresponding enable_mask bit is set */
    165
    166		if (!(register_bit & gpe_register_info->enable_mask)) {
    167			return (AE_BAD_PARAMETER);
    168		}
    169
    170		ACPI_FALLTHROUGH;
    171
    172	case ACPI_GPE_ENABLE:
    173
    174		ACPI_SET_BIT(enable_mask, register_bit);
    175		break;
    176
    177	case ACPI_GPE_DISABLE:
    178
    179		ACPI_CLEAR_BIT(enable_mask, register_bit);
    180		break;
    181
    182	default:
    183
    184		ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action));
    185		return (AE_BAD_PARAMETER);
    186	}
    187
    188	if (!(register_bit & gpe_register_info->mask_for_run)) {
    189
    190		/* Write the updated enable mask */
    191
    192		status = acpi_hw_gpe_write(enable_mask,
    193					   &gpe_register_info->enable_address);
    194	}
    195	return (status);
    196}
    197
    198/******************************************************************************
    199 *
    200 * FUNCTION:    acpi_hw_clear_gpe
    201 *
    202 * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
    203 *
    204 * RETURN:      Status
    205 *
    206 * DESCRIPTION: Clear the status bit for a single GPE.
    207 *
    208 ******************************************************************************/
    209
    210acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info)
    211{
    212	struct acpi_gpe_register_info *gpe_register_info;
    213	acpi_status status;
    214	u32 register_bit;
    215
    216	ACPI_FUNCTION_ENTRY();
    217
    218	/* Get the info block for the entire GPE register */
    219
    220	gpe_register_info = gpe_event_info->register_info;
    221	if (!gpe_register_info) {
    222		return (AE_NOT_EXIST);
    223	}
    224
    225	/*
    226	 * Write a one to the appropriate bit in the status register to
    227	 * clear this GPE.
    228	 */
    229	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
    230
    231	status = acpi_hw_gpe_write(register_bit,
    232				   &gpe_register_info->status_address);
    233	return (status);
    234}
    235
    236/******************************************************************************
    237 *
    238 * FUNCTION:    acpi_hw_get_gpe_status
    239 *
    240 * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
    241 *              event_status        - Where the GPE status is returned
    242 *
    243 * RETURN:      Status
    244 *
    245 * DESCRIPTION: Return the status of a single GPE.
    246 *
    247 ******************************************************************************/
    248
    249acpi_status
    250acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
    251		       acpi_event_status *event_status)
    252{
    253	u64 in_byte;
    254	u32 register_bit;
    255	struct acpi_gpe_register_info *gpe_register_info;
    256	acpi_event_status local_event_status = 0;
    257	acpi_status status;
    258
    259	ACPI_FUNCTION_ENTRY();
    260
    261	if (!event_status) {
    262		return (AE_BAD_PARAMETER);
    263	}
    264
    265	/* GPE currently handled? */
    266
    267	if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
    268	    ACPI_GPE_DISPATCH_NONE) {
    269		local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
    270	}
    271
    272	/* Get the info block for the entire GPE register */
    273
    274	gpe_register_info = gpe_event_info->register_info;
    275
    276	/* Get the register bitmask for this GPE */
    277
    278	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
    279
    280	/* GPE currently enabled? (enabled for runtime?) */
    281
    282	if (register_bit & gpe_register_info->enable_for_run) {
    283		local_event_status |= ACPI_EVENT_FLAG_ENABLED;
    284	}
    285
    286	/* GPE currently masked? (masked for runtime?) */
    287
    288	if (register_bit & gpe_register_info->mask_for_run) {
    289		local_event_status |= ACPI_EVENT_FLAG_MASKED;
    290	}
    291
    292	/* GPE enabled for wake? */
    293
    294	if (register_bit & gpe_register_info->enable_for_wake) {
    295		local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
    296	}
    297
    298	/* GPE currently enabled (enable bit == 1)? */
    299
    300	status = acpi_hw_gpe_read(&in_byte, &gpe_register_info->enable_address);
    301	if (ACPI_FAILURE(status)) {
    302		return (status);
    303	}
    304
    305	if (register_bit & in_byte) {
    306		local_event_status |= ACPI_EVENT_FLAG_ENABLE_SET;
    307	}
    308
    309	/* GPE currently active (status bit == 1)? */
    310
    311	status = acpi_hw_gpe_read(&in_byte, &gpe_register_info->status_address);
    312	if (ACPI_FAILURE(status)) {
    313		return (status);
    314	}
    315
    316	if (register_bit & in_byte) {
    317		local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
    318	}
    319
    320	/* Set return value */
    321
    322	(*event_status) = local_event_status;
    323	return (AE_OK);
    324}
    325
    326/******************************************************************************
    327 *
    328 * FUNCTION:    acpi_hw_gpe_enable_write
    329 *
    330 * PARAMETERS:  enable_mask         - Bit mask to write to the GPE register
    331 *              gpe_register_info   - Gpe Register info
    332 *
    333 * RETURN:      Status
    334 *
    335 * DESCRIPTION: Write the enable mask byte to the given GPE register.
    336 *
    337 ******************************************************************************/
    338
    339static acpi_status
    340acpi_hw_gpe_enable_write(u8 enable_mask,
    341			 struct acpi_gpe_register_info *gpe_register_info)
    342{
    343	acpi_status status;
    344
    345	gpe_register_info->enable_mask = enable_mask;
    346
    347	status = acpi_hw_gpe_write(enable_mask,
    348				   &gpe_register_info->enable_address);
    349	return (status);
    350}
    351
    352/******************************************************************************
    353 *
    354 * FUNCTION:    acpi_hw_disable_gpe_block
    355 *
    356 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
    357 *              gpe_block           - Gpe Block info
    358 *
    359 * RETURN:      Status
    360 *
    361 * DESCRIPTION: Disable all GPEs within a single GPE block
    362 *
    363 ******************************************************************************/
    364
    365acpi_status
    366acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
    367			  struct acpi_gpe_block_info *gpe_block, void *context)
    368{
    369	u32 i;
    370	acpi_status status;
    371
    372	/* Examine each GPE Register within the block */
    373
    374	for (i = 0; i < gpe_block->register_count; i++) {
    375
    376		/* Disable all GPEs in this register */
    377
    378		status =
    379		    acpi_hw_gpe_enable_write(0x00,
    380					     &gpe_block->register_info[i]);
    381		if (ACPI_FAILURE(status)) {
    382			return (status);
    383		}
    384	}
    385
    386	return (AE_OK);
    387}
    388
    389/******************************************************************************
    390 *
    391 * FUNCTION:    acpi_hw_clear_gpe_block
    392 *
    393 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
    394 *              gpe_block           - Gpe Block info
    395 *
    396 * RETURN:      Status
    397 *
    398 * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
    399 *
    400 ******************************************************************************/
    401
    402acpi_status
    403acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
    404			struct acpi_gpe_block_info *gpe_block, void *context)
    405{
    406	u32 i;
    407	acpi_status status;
    408
    409	/* Examine each GPE Register within the block */
    410
    411	for (i = 0; i < gpe_block->register_count; i++) {
    412
    413		/* Clear status on all GPEs in this register */
    414
    415		status = acpi_hw_gpe_write(0xFF,
    416					   &gpe_block->register_info[i].status_address);
    417		if (ACPI_FAILURE(status)) {
    418			return (status);
    419		}
    420	}
    421
    422	return (AE_OK);
    423}
    424
    425/******************************************************************************
    426 *
    427 * FUNCTION:    acpi_hw_enable_runtime_gpe_block
    428 *
    429 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
    430 *              gpe_block           - Gpe Block info
    431 *
    432 * RETURN:      Status
    433 *
    434 * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
    435 *              combination wake/run GPEs.
    436 *
    437 ******************************************************************************/
    438
    439acpi_status
    440acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
    441				 struct acpi_gpe_block_info *gpe_block,
    442				 void *context)
    443{
    444	u32 i;
    445	acpi_status status;
    446	struct acpi_gpe_register_info *gpe_register_info;
    447	u8 enable_mask;
    448
    449	/* NOTE: assumes that all GPEs are currently disabled */
    450
    451	/* Examine each GPE Register within the block */
    452
    453	for (i = 0; i < gpe_block->register_count; i++) {
    454		gpe_register_info = &gpe_block->register_info[i];
    455		if (!gpe_register_info->enable_for_run) {
    456			continue;
    457		}
    458
    459		/* Enable all "runtime" GPEs in this register */
    460
    461		enable_mask = gpe_register_info->enable_for_run &
    462		    ~gpe_register_info->mask_for_run;
    463		status =
    464		    acpi_hw_gpe_enable_write(enable_mask, gpe_register_info);
    465		if (ACPI_FAILURE(status)) {
    466			return (status);
    467		}
    468	}
    469
    470	return (AE_OK);
    471}
    472
    473/******************************************************************************
    474 *
    475 * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
    476 *
    477 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
    478 *              gpe_block           - Gpe Block info
    479 *
    480 * RETURN:      Status
    481 *
    482 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
    483 *              combination wake/run GPEs.
    484 *
    485 ******************************************************************************/
    486
    487static acpi_status
    488acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
    489				struct acpi_gpe_block_info *gpe_block,
    490				void *context)
    491{
    492	u32 i;
    493	acpi_status status;
    494	struct acpi_gpe_register_info *gpe_register_info;
    495
    496	/* Examine each GPE Register within the block */
    497
    498	for (i = 0; i < gpe_block->register_count; i++) {
    499		gpe_register_info = &gpe_block->register_info[i];
    500
    501		/*
    502		 * Enable all "wake" GPEs in this register and disable the
    503		 * remaining ones.
    504		 */
    505
    506		status =
    507		    acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake,
    508					     gpe_register_info);
    509		if (ACPI_FAILURE(status)) {
    510			return (status);
    511		}
    512	}
    513
    514	return (AE_OK);
    515}
    516
    517struct acpi_gpe_block_status_context {
    518	struct acpi_gpe_register_info *gpe_skip_register_info;
    519	u8 gpe_skip_mask;
    520	u8 retval;
    521};
    522
    523/******************************************************************************
    524 *
    525 * FUNCTION:    acpi_hw_get_gpe_block_status
    526 *
    527 * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
    528 *              gpe_block           - Gpe Block info
    529 *              context             - GPE list walk context data
    530 *
    531 * RETURN:      Success
    532 *
    533 * DESCRIPTION: Produce a combined GPE status bits mask for the given block.
    534 *
    535 ******************************************************************************/
    536
    537static acpi_status
    538acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
    539			     struct acpi_gpe_block_info *gpe_block,
    540			     void *context)
    541{
    542	struct acpi_gpe_block_status_context *c = context;
    543	struct acpi_gpe_register_info *gpe_register_info;
    544	u64 in_enable, in_status;
    545	acpi_status status;
    546	u8 ret_mask;
    547	u32 i;
    548
    549	/* Examine each GPE Register within the block */
    550
    551	for (i = 0; i < gpe_block->register_count; i++) {
    552		gpe_register_info = &gpe_block->register_info[i];
    553
    554		status = acpi_hw_gpe_read(&in_enable,
    555					  &gpe_register_info->enable_address);
    556		if (ACPI_FAILURE(status)) {
    557			continue;
    558		}
    559
    560		status = acpi_hw_gpe_read(&in_status,
    561					  &gpe_register_info->status_address);
    562		if (ACPI_FAILURE(status)) {
    563			continue;
    564		}
    565
    566		ret_mask = in_enable & in_status;
    567		if (ret_mask && c->gpe_skip_register_info == gpe_register_info) {
    568			ret_mask &= ~c->gpe_skip_mask;
    569		}
    570		c->retval |= ret_mask;
    571	}
    572
    573	return (AE_OK);
    574}
    575
    576/******************************************************************************
    577 *
    578 * FUNCTION:    acpi_hw_disable_all_gpes
    579 *
    580 * PARAMETERS:  None
    581 *
    582 * RETURN:      Status
    583 *
    584 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
    585 *
    586 ******************************************************************************/
    587
    588acpi_status acpi_hw_disable_all_gpes(void)
    589{
    590	acpi_status status;
    591
    592	ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
    593
    594	status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
    595	return_ACPI_STATUS(status);
    596}
    597
    598/******************************************************************************
    599 *
    600 * FUNCTION:    acpi_hw_enable_all_runtime_gpes
    601 *
    602 * PARAMETERS:  None
    603 *
    604 * RETURN:      Status
    605 *
    606 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
    607 *
    608 ******************************************************************************/
    609
    610acpi_status acpi_hw_enable_all_runtime_gpes(void)
    611{
    612	acpi_status status;
    613
    614	ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
    615
    616	status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
    617	return_ACPI_STATUS(status);
    618}
    619
    620/******************************************************************************
    621 *
    622 * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
    623 *
    624 * PARAMETERS:  None
    625 *
    626 * RETURN:      Status
    627 *
    628 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
    629 *
    630 ******************************************************************************/
    631
    632acpi_status acpi_hw_enable_all_wakeup_gpes(void)
    633{
    634	acpi_status status;
    635
    636	ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
    637
    638	status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
    639	return_ACPI_STATUS(status);
    640}
    641
    642/******************************************************************************
    643 *
    644 * FUNCTION:    acpi_hw_check_all_gpes
    645 *
    646 * PARAMETERS:  gpe_skip_device      - GPE devoce of the GPE to skip
    647 *              gpe_skip_number      - Number of the GPE to skip
    648 *
    649 * RETURN:      Combined status of all GPEs
    650 *
    651 * DESCRIPTION: Check all enabled GPEs in all GPE blocks, except for the one
    652 *              represented by the "skip" arguments, and return TRUE if the
    653 *              status bit is set for at least one of them of FALSE otherwise.
    654 *
    655 ******************************************************************************/
    656
    657u8 acpi_hw_check_all_gpes(acpi_handle gpe_skip_device, u32 gpe_skip_number)
    658{
    659	struct acpi_gpe_block_status_context context = {
    660		.gpe_skip_register_info = NULL,
    661		.retval = 0,
    662	};
    663	struct acpi_gpe_event_info *gpe_event_info;
    664	acpi_cpu_flags flags;
    665
    666	ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes);
    667
    668	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
    669
    670	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_skip_device,
    671						    gpe_skip_number);
    672	if (gpe_event_info) {
    673		context.gpe_skip_register_info = gpe_event_info->register_info;
    674		context.gpe_skip_mask = acpi_hw_get_gpe_register_bit(gpe_event_info);
    675	}
    676
    677	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
    678
    679	(void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &context);
    680	return (context.retval != 0);
    681}
    682
    683#endif				/* !ACPI_REDUCED_HARDWARE */