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

processor_pdc.c (4700B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2005 Intel Corporation
      4 * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
      5 *
      6 *      Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
      7 *      - Added _PDC for platforms with Intel CPUs
      8 */
      9
     10#define pr_fmt(fmt) "ACPI: " fmt
     11
     12#include <linux/dmi.h>
     13#include <linux/slab.h>
     14#include <linux/acpi.h>
     15#include <acpi/processor.h>
     16
     17#include "internal.h"
     18
     19static bool __init processor_physically_present(acpi_handle handle)
     20{
     21	int cpuid, type;
     22	u32 acpi_id;
     23	acpi_status status;
     24	acpi_object_type acpi_type;
     25	unsigned long long tmp;
     26	union acpi_object object = { 0 };
     27	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
     28
     29	status = acpi_get_type(handle, &acpi_type);
     30	if (ACPI_FAILURE(status))
     31		return false;
     32
     33	switch (acpi_type) {
     34	case ACPI_TYPE_PROCESSOR:
     35		status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
     36		if (ACPI_FAILURE(status))
     37			return false;
     38		acpi_id = object.processor.proc_id;
     39		break;
     40	case ACPI_TYPE_DEVICE:
     41		status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
     42		if (ACPI_FAILURE(status))
     43			return false;
     44		acpi_id = tmp;
     45		break;
     46	default:
     47		return false;
     48	}
     49
     50	type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
     51	cpuid = acpi_get_cpuid(handle, type, acpi_id);
     52
     53	return !invalid_logical_cpuid(cpuid);
     54}
     55
     56static void acpi_set_pdc_bits(u32 *buf)
     57{
     58	buf[0] = ACPI_PDC_REVISION_ID;
     59	buf[1] = 1;
     60
     61	/* Enable coordination with firmware's _TSD info */
     62	buf[2] = ACPI_PDC_SMP_T_SWCOORD;
     63
     64	/* Twiddle arch-specific bits needed for _PDC */
     65	arch_acpi_set_pdc_bits(buf);
     66}
     67
     68static struct acpi_object_list *acpi_processor_alloc_pdc(void)
     69{
     70	struct acpi_object_list *obj_list;
     71	union acpi_object *obj;
     72	u32 *buf;
     73
     74	/* allocate and initialize pdc. It will be used later. */
     75	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
     76	if (!obj_list)
     77		goto out;
     78
     79	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
     80	if (!obj) {
     81		kfree(obj_list);
     82		goto out;
     83	}
     84
     85	buf = kmalloc(12, GFP_KERNEL);
     86	if (!buf) {
     87		kfree(obj);
     88		kfree(obj_list);
     89		goto out;
     90	}
     91
     92	acpi_set_pdc_bits(buf);
     93
     94	obj->type = ACPI_TYPE_BUFFER;
     95	obj->buffer.length = 12;
     96	obj->buffer.pointer = (u8 *) buf;
     97	obj_list->count = 1;
     98	obj_list->pointer = obj;
     99
    100	return obj_list;
    101out:
    102	pr_err("Memory allocation error\n");
    103	return NULL;
    104}
    105
    106/*
    107 * _PDC is required for a BIOS-OS handshake for most of the newer
    108 * ACPI processor features.
    109 */
    110static acpi_status
    111acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
    112{
    113	acpi_status status = AE_OK;
    114
    115	if (boot_option_idle_override == IDLE_NOMWAIT) {
    116		/*
    117		 * If mwait is disabled for CPU C-states, the C2C3_FFH access
    118		 * mode will be disabled in the parameter of _PDC object.
    119		 * Of course C1_FFH access mode will also be disabled.
    120		 */
    121		union acpi_object *obj;
    122		u32 *buffer = NULL;
    123
    124		obj = pdc_in->pointer;
    125		buffer = (u32 *)(obj->buffer.pointer);
    126		buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
    127
    128	}
    129	status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
    130
    131	if (ACPI_FAILURE(status))
    132		acpi_handle_debug(handle,
    133		    "Could not evaluate _PDC, using legacy perf control\n");
    134
    135	return status;
    136}
    137
    138void acpi_processor_set_pdc(acpi_handle handle)
    139{
    140	struct acpi_object_list *obj_list;
    141
    142	if (arch_has_acpi_pdc() == false)
    143		return;
    144
    145	obj_list = acpi_processor_alloc_pdc();
    146	if (!obj_list)
    147		return;
    148
    149	acpi_processor_eval_pdc(handle, obj_list);
    150
    151	kfree(obj_list->pointer->buffer.pointer);
    152	kfree(obj_list->pointer);
    153	kfree(obj_list);
    154}
    155
    156static acpi_status __init
    157early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
    158{
    159	if (processor_physically_present(handle) == false)
    160		return AE_OK;
    161
    162	acpi_processor_set_pdc(handle);
    163	return AE_OK;
    164}
    165
    166static int __init set_no_mwait(const struct dmi_system_id *id)
    167{
    168	pr_notice("%s detected - disabling mwait for CPU C-states\n",
    169		  id->ident);
    170	boot_option_idle_override = IDLE_NOMWAIT;
    171	return 0;
    172}
    173
    174static const struct dmi_system_id processor_idle_dmi_table[] __initconst = {
    175	{
    176	set_no_mwait, "Extensa 5220", {
    177	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
    178	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
    179	DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
    180	DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
    181	{},
    182};
    183
    184static void __init processor_dmi_check(void)
    185{
    186	/*
    187	 * Check whether the system is DMI table. If yes, OSPM
    188	 * should not use mwait for CPU-states.
    189	 */
    190	dmi_check_system(processor_idle_dmi_table);
    191}
    192
    193void __init acpi_early_processor_set_pdc(void)
    194{
    195	processor_dmi_check();
    196
    197	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
    198			    ACPI_UINT32_MAX,
    199			    early_init_pdc, NULL, NULL, NULL);
    200	acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL);
    201}