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

utils.c (13895B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * X86 ACPI Utility Functions
      4 *
      5 * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
      6 *
      7 * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
      8 * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
      9 */
     10
     11#define pr_fmt(fmt) "ACPI: " fmt
     12
     13#include <linux/acpi.h>
     14#include <linux/dmi.h>
     15#include <linux/platform_device.h>
     16#include <asm/cpu_device_id.h>
     17#include <asm/intel-family.h>
     18#include "../internal.h"
     19
     20/*
     21 * Some ACPI devices are hidden (status == 0x0) in recent BIOS-es because
     22 * some recent Windows drivers bind to one device but poke at multiple
     23 * devices at the same time, so the others get hidden.
     24 *
     25 * Some BIOS-es (temporarily) hide specific APCI devices to work around Windows
     26 * driver bugs. We use DMI matching to match known cases of this.
     27 *
     28 * Likewise sometimes some not-actually present devices are sometimes
     29 * reported as present, which may cause issues.
     30 *
     31 * We work around this by using the below quirk list to override the status
     32 * reported by the _STA method with a fixed value (ACPI_STA_DEFAULT or 0).
     33 * Note this MUST only be done for devices where this is safe.
     34 *
     35 * This status overriding is limited to specific CPU (SoC) models both to
     36 * avoid potentially causing trouble on other models and because some HIDs
     37 * are re-used on different SoCs for completely different devices.
     38 */
     39struct override_status_id {
     40	struct acpi_device_id hid[2];
     41	struct x86_cpu_id cpu_ids[2];
     42	struct dmi_system_id dmi_ids[2]; /* Optional */
     43	const char *uid;
     44	const char *path;
     45	unsigned long long status;
     46};
     47
     48#define ENTRY(status, hid, uid, path, cpu_model, dmi...) {		\
     49	{ { hid, }, {} },						\
     50	{ X86_MATCH_INTEL_FAM6_MODEL(cpu_model, NULL), {} },		\
     51	{ { .matches = dmi }, {} },					\
     52	uid,								\
     53	path,								\
     54	status,								\
     55}
     56
     57#define PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \
     58	ENTRY(ACPI_STA_DEFAULT, hid, uid, NULL, cpu_model, dmi)
     59
     60#define NOT_PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \
     61	ENTRY(0, hid, uid, NULL, cpu_model, dmi)
     62
     63#define PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \
     64	ENTRY(ACPI_STA_DEFAULT, "", NULL, path, cpu_model, dmi)
     65
     66#define NOT_PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \
     67	ENTRY(0, "", NULL, path, cpu_model, dmi)
     68
     69static const struct override_status_id override_status_ids[] = {
     70	/*
     71	 * Bay / Cherry Trail PWM directly poked by GPU driver in win10,
     72	 * but Linux uses a separate PWM driver, harmless if not used.
     73	 */
     74	PRESENT_ENTRY_HID("80860F09", "1", ATOM_SILVERMONT, {}),
     75	PRESENT_ENTRY_HID("80862288", "1", ATOM_AIRMONT, {}),
     76
     77	/* The Xiaomi Mi Pad 2 uses PWM2 for touchkeys backlight control */
     78	PRESENT_ENTRY_HID("80862289", "2", ATOM_AIRMONT, {
     79		DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
     80		DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
     81	      }),
     82
     83	/*
     84	 * The INT0002 device is necessary to clear wakeup interrupt sources
     85	 * on Cherry Trail devices, without it we get nobody cared IRQ msgs.
     86	 */
     87	PRESENT_ENTRY_HID("INT0002", "1", ATOM_AIRMONT, {}),
     88	/*
     89	 * On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides
     90	 * the touchscreen ACPI device until a certain time
     91	 * after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed
     92	 * *and* _STA has been called at least 3 times since.
     93	 */
     94	PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, {
     95		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
     96		DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
     97	      }),
     98	PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, {
     99		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
    100		DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"),
    101	      }),
    102
    103	/*
    104	 * The GPD win BIOS dated 20170221 has disabled the accelerometer, the
    105	 * drivers sometimes cause crashes under Windows and this is how the
    106	 * manufacturer has solved this :|  The DMI match may not seem unique,
    107	 * but it is. In the 67000+ DMI decode dumps from linux-hardware.org
    108	 * only 116 have board_vendor set to "AMI Corporation" and of those 116
    109	 * only the GPD win and pocket entries' board_name is "Default string".
    110	 *
    111	 * Unfortunately the GPD pocket also uses these strings and its BIOS
    112	 * was copy-pasted from the GPD win, so it has a disabled KIOX000A
    113	 * node which we should not enable, thus we also check the BIOS date.
    114	 */
    115	PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
    116		DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
    117		DMI_MATCH(DMI_BOARD_NAME, "Default string"),
    118		DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
    119		DMI_MATCH(DMI_BIOS_DATE, "02/21/2017")
    120	      }),
    121	PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
    122		DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
    123		DMI_MATCH(DMI_BOARD_NAME, "Default string"),
    124		DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
    125		DMI_MATCH(DMI_BIOS_DATE, "03/20/2017")
    126	      }),
    127	PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
    128		DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
    129		DMI_MATCH(DMI_BOARD_NAME, "Default string"),
    130		DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
    131		DMI_MATCH(DMI_BIOS_DATE, "05/25/2017")
    132	      }),
    133
    134	/*
    135	 * The GPD win/pocket have a PCI wifi card, but its DSDT has the SDIO
    136	 * mmc controller enabled and that has a child-device which _PS3
    137	 * method sets a GPIO causing the PCI wifi card to turn off.
    138	 * See above remark about uniqueness of the DMI match.
    139	 */
    140	NOT_PRESENT_ENTRY_PATH("\\_SB_.PCI0.SDHB.BRC1", ATOM_AIRMONT, {
    141		DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
    142		DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
    143		DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
    144		DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
    145	      }),
    146};
    147
    148bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status)
    149{
    150	bool ret = false;
    151	unsigned int i;
    152
    153	for (i = 0; i < ARRAY_SIZE(override_status_ids); i++) {
    154		if (!x86_match_cpu(override_status_ids[i].cpu_ids))
    155			continue;
    156
    157		if (override_status_ids[i].dmi_ids[0].matches[0].slot &&
    158		    !dmi_check_system(override_status_ids[i].dmi_ids))
    159			continue;
    160
    161		if (override_status_ids[i].path) {
    162			struct acpi_buffer path = { ACPI_ALLOCATE_BUFFER, NULL };
    163			bool match;
    164
    165			if (acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &path))
    166				continue;
    167
    168			match = strcmp((char *)path.pointer, override_status_ids[i].path) == 0;
    169			kfree(path.pointer);
    170
    171			if (!match)
    172				continue;
    173		} else {
    174			if (acpi_match_device_ids(adev, override_status_ids[i].hid))
    175				continue;
    176
    177			if (!adev->pnp.unique_id ||
    178			    strcmp(adev->pnp.unique_id, override_status_ids[i].uid))
    179				continue;
    180		}
    181
    182		*status = override_status_ids[i].status;
    183		ret = true;
    184		break;
    185	}
    186
    187	return ret;
    188}
    189
    190/*
    191 * AMD systems from Renoir and Lucienne *require* that the NVME controller
    192 * is put into D3 over a Modern Standby / suspend-to-idle cycle.
    193 *
    194 * This is "typically" accomplished using the `StorageD3Enable`
    195 * property in the _DSD that is checked via the `acpi_storage_d3` function
    196 * but this property was introduced after many of these systems launched
    197 * and most OEM systems don't have it in their BIOS.
    198 *
    199 * The Microsoft documentation for StorageD3Enable mentioned that Windows has
    200 * a hardcoded allowlist for D3 support, which was used for these platforms.
    201 *
    202 * This allows quirking on Linux in a similar fashion.
    203 */
    204static const struct x86_cpu_id storage_d3_cpu_ids[] = {
    205	X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 96, NULL),	/* Renoir */
    206	X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 104, NULL),	/* Lucienne */
    207	{}
    208};
    209
    210bool force_storage_d3(void)
    211{
    212	return x86_match_cpu(storage_d3_cpu_ids);
    213}
    214
    215/*
    216 * x86 ACPI boards which ship with only Android as their factory image usually
    217 * declare a whole bunch of bogus I2C devices in their ACPI tables and sometimes
    218 * there are issues with serdev devices on these boards too, e.g. the resource
    219 * points to the wrong serdev_controller.
    220 *
    221 * Instantiating I2C / serdev devs for these bogus devs causes various issues,
    222 * e.g. GPIO/IRQ resource conflicts because sometimes drivers do bind to them.
    223 * The Android x86 kernel fork shipped on these devices has some special code
    224 * to remove the bogus I2C clients (and AFAICT serdevs are ignored completely).
    225 *
    226 * The acpi_quirk_skip_*_enumeration() functions below are used by the I2C or
    227 * serdev code to skip instantiating any I2C or serdev devs on broken boards.
    228 *
    229 * In case of I2C an exception is made for HIDs on the i2c_acpi_known_good_ids
    230 * list. These are known to always be correct (and in case of the audio-codecs
    231 * the drivers heavily rely on the codec being enumerated through ACPI).
    232 *
    233 * Note these boards typically do actually have I2C and serdev devices,
    234 * just different ones then the ones described in their DSDT. The devices
    235 * which are actually present are manually instantiated by the
    236 * drivers/platform/x86/x86-android-tablets.c kernel module.
    237 */
    238#define ACPI_QUIRK_SKIP_I2C_CLIENTS				BIT(0)
    239#define ACPI_QUIRK_UART1_TTY_UART2_SKIP				BIT(1)
    240#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY			BIT(2)
    241#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY			BIT(3)
    242
    243static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
    244	/*
    245	 * 1. Devices with only the skip / don't-skip AC and battery quirks,
    246	 *    sorted alphabetically.
    247	 */
    248	{
    249		/* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */
    250		.matches = {
    251			DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
    252		},
    253		.driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY
    254	},
    255	{
    256		/* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
    257		.matches = {
    258			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
    259			DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
    260			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
    261		},
    262		.driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY
    263	},
    264
    265	/*
    266	 * 2. Devices which also have the skip i2c/serdev quirks and which
    267	 *    need the x86-android-tablets module to properly work.
    268	 */
    269#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
    270	{
    271		.matches = {
    272			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
    273			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
    274		},
    275		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
    276					ACPI_QUIRK_UART1_TTY_UART2_SKIP |
    277					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
    278	},
    279	{
    280		.matches = {
    281			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
    282			DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
    283		},
    284		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
    285					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
    286	},
    287	{
    288		/* Lenovo Yoga Tablet 1050F/L */
    289		.matches = {
    290			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
    291			DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
    292			DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
    293			/* Partial match on beginning of BIOS version */
    294			DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
    295		},
    296		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
    297					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
    298	},
    299	{
    300		/* Nextbook Ares 8 */
    301		.matches = {
    302			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
    303			DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
    304		},
    305		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
    306					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
    307	},
    308	{
    309		/* Whitelabel (sold as various brands) TM800A550L */
    310		.matches = {
    311			DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
    312			DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
    313			/* Above strings are too generic, also match on BIOS version */
    314			DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
    315		},
    316		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
    317					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
    318	},
    319#endif
    320	{}
    321};
    322
    323#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
    324static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
    325	{ "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
    326	{ "INT33F4", 0 },  /* X-Powers AXP288 PMIC */
    327	{ "INT33FD", 0 },  /* Intel Crystal Cove PMIC */
    328	{ "NPCE69A", 0 },  /* Asus Transformer keyboard dock */
    329	{}
    330};
    331
    332bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
    333{
    334	const struct dmi_system_id *dmi_id;
    335	long quirks;
    336
    337	dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
    338	if (!dmi_id)
    339		return false;
    340
    341	quirks = (unsigned long)dmi_id->driver_data;
    342	if (!(quirks & ACPI_QUIRK_SKIP_I2C_CLIENTS))
    343		return false;
    344
    345	return acpi_match_device_ids(adev, i2c_acpi_known_good_ids);
    346}
    347EXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration);
    348
    349int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
    350{
    351	struct acpi_device *adev = ACPI_COMPANION(controller_parent);
    352	const struct dmi_system_id *dmi_id;
    353	long quirks = 0;
    354
    355	*skip = false;
    356
    357	/* !dev_is_platform() to not match on PNP enumerated debug UARTs */
    358	if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent))
    359		return 0;
    360
    361	dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
    362	if (dmi_id)
    363		quirks = (unsigned long)dmi_id->driver_data;
    364
    365	if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) {
    366		if (!strcmp(adev->pnp.unique_id, "1"))
    367			return -ENODEV; /* Create tty cdev instead of serdev */
    368
    369		if (!strcmp(adev->pnp.unique_id, "2"))
    370			*skip = true;
    371	}
    372
    373	return 0;
    374}
    375EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration);
    376#endif
    377
    378/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
    379static const struct {
    380	const char *hid;
    381	int hrv;
    382} acpi_skip_ac_and_battery_pmic_ids[] = {
    383	{ "INT33F4", -1 }, /* X-Powers AXP288 PMIC */
    384	{ "INT34D3",  3 }, /* Intel Cherrytrail Whiskey Cove PMIC */
    385};
    386
    387bool acpi_quirk_skip_acpi_ac_and_battery(void)
    388{
    389	const struct dmi_system_id *dmi_id;
    390	long quirks = 0;
    391	int i;
    392
    393	dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
    394	if (dmi_id)
    395		quirks = (unsigned long)dmi_id->driver_data;
    396
    397	if (quirks & ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY)
    398		return true;
    399
    400	if (quirks & ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY)
    401		return false;
    402
    403	for (i = 0; i < ARRAY_SIZE(acpi_skip_ac_and_battery_pmic_ids); i++) {
    404		if (acpi_dev_present(acpi_skip_ac_and_battery_pmic_ids[i].hid, "1",
    405				     acpi_skip_ac_and_battery_pmic_ids[i].hrv)) {
    406			pr_info_once("found native %s PMIC, skipping ACPI AC and battery devices\n",
    407				     acpi_skip_ac_and_battery_pmic_ids[i].hid);
    408			return true;
    409		}
    410	}
    411
    412	return false;
    413}
    414EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery);