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

tsx.c (7516B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Intel Transactional Synchronization Extensions (TSX) control.
      4 *
      5 * Copyright (C) 2019-2021 Intel Corporation
      6 *
      7 * Author:
      8 *	Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
      9 */
     10
     11#include <linux/cpufeature.h>
     12
     13#include <asm/cmdline.h>
     14
     15#include "cpu.h"
     16
     17#undef pr_fmt
     18#define pr_fmt(fmt) "tsx: " fmt
     19
     20enum tsx_ctrl_states tsx_ctrl_state __ro_after_init = TSX_CTRL_NOT_SUPPORTED;
     21
     22static void tsx_disable(void)
     23{
     24	u64 tsx;
     25
     26	rdmsrl(MSR_IA32_TSX_CTRL, tsx);
     27
     28	/* Force all transactions to immediately abort */
     29	tsx |= TSX_CTRL_RTM_DISABLE;
     30
     31	/*
     32	 * Ensure TSX support is not enumerated in CPUID.
     33	 * This is visible to userspace and will ensure they
     34	 * do not waste resources trying TSX transactions that
     35	 * will always abort.
     36	 */
     37	tsx |= TSX_CTRL_CPUID_CLEAR;
     38
     39	wrmsrl(MSR_IA32_TSX_CTRL, tsx);
     40}
     41
     42static void tsx_enable(void)
     43{
     44	u64 tsx;
     45
     46	rdmsrl(MSR_IA32_TSX_CTRL, tsx);
     47
     48	/* Enable the RTM feature in the cpu */
     49	tsx &= ~TSX_CTRL_RTM_DISABLE;
     50
     51	/*
     52	 * Ensure TSX support is enumerated in CPUID.
     53	 * This is visible to userspace and will ensure they
     54	 * can enumerate and use the TSX feature.
     55	 */
     56	tsx &= ~TSX_CTRL_CPUID_CLEAR;
     57
     58	wrmsrl(MSR_IA32_TSX_CTRL, tsx);
     59}
     60
     61static bool tsx_ctrl_is_supported(void)
     62{
     63	u64 ia32_cap = x86_read_arch_cap_msr();
     64
     65	/*
     66	 * TSX is controlled via MSR_IA32_TSX_CTRL.  However, support for this
     67	 * MSR is enumerated by ARCH_CAP_TSX_MSR bit in MSR_IA32_ARCH_CAPABILITIES.
     68	 *
     69	 * TSX control (aka MSR_IA32_TSX_CTRL) is only available after a
     70	 * microcode update on CPUs that have their MSR_IA32_ARCH_CAPABILITIES
     71	 * bit MDS_NO=1. CPUs with MDS_NO=0 are not planned to get
     72	 * MSR_IA32_TSX_CTRL support even after a microcode update. Thus,
     73	 * tsx= cmdline requests will do nothing on CPUs without
     74	 * MSR_IA32_TSX_CTRL support.
     75	 */
     76	return !!(ia32_cap & ARCH_CAP_TSX_CTRL_MSR);
     77}
     78
     79static enum tsx_ctrl_states x86_get_tsx_auto_mode(void)
     80{
     81	if (boot_cpu_has_bug(X86_BUG_TAA))
     82		return TSX_CTRL_DISABLE;
     83
     84	return TSX_CTRL_ENABLE;
     85}
     86
     87/*
     88 * Disabling TSX is not a trivial business.
     89 *
     90 * First of all, there's a CPUID bit: X86_FEATURE_RTM_ALWAYS_ABORT
     91 * which says that TSX is practically disabled (all transactions are
     92 * aborted by default). When that bit is set, the kernel unconditionally
     93 * disables TSX.
     94 *
     95 * In order to do that, however, it needs to dance a bit:
     96 *
     97 * 1. The first method to disable it is through MSR_TSX_FORCE_ABORT and
     98 * the MSR is present only when *two* CPUID bits are set:
     99 *
    100 * - X86_FEATURE_RTM_ALWAYS_ABORT
    101 * - X86_FEATURE_TSX_FORCE_ABORT
    102 *
    103 * 2. The second method is for CPUs which do not have the above-mentioned
    104 * MSR: those use a different MSR - MSR_IA32_TSX_CTRL and disable TSX
    105 * through that one. Those CPUs can also have the initially mentioned
    106 * CPUID bit X86_FEATURE_RTM_ALWAYS_ABORT set and for those the same strategy
    107 * applies: TSX gets disabled unconditionally.
    108 *
    109 * When either of the two methods are present, the kernel disables TSX and
    110 * clears the respective RTM and HLE feature flags.
    111 *
    112 * An additional twist in the whole thing presents late microcode loading
    113 * which, when done, may cause for the X86_FEATURE_RTM_ALWAYS_ABORT CPUID
    114 * bit to be set after the update.
    115 *
    116 * A subsequent hotplug operation on any logical CPU except the BSP will
    117 * cause for the supported CPUID feature bits to get re-detected and, if
    118 * RTM and HLE get cleared all of a sudden, but, userspace did consult
    119 * them before the update, then funny explosions will happen. Long story
    120 * short: the kernel doesn't modify CPUID feature bits after booting.
    121 *
    122 * That's why, this function's call in init_intel() doesn't clear the
    123 * feature flags.
    124 */
    125static void tsx_clear_cpuid(void)
    126{
    127	u64 msr;
    128
    129	/*
    130	 * MSR_TFA_TSX_CPUID_CLEAR bit is only present when both CPUID
    131	 * bits RTM_ALWAYS_ABORT and TSX_FORCE_ABORT are present.
    132	 */
    133	if (boot_cpu_has(X86_FEATURE_RTM_ALWAYS_ABORT) &&
    134	    boot_cpu_has(X86_FEATURE_TSX_FORCE_ABORT)) {
    135		rdmsrl(MSR_TSX_FORCE_ABORT, msr);
    136		msr |= MSR_TFA_TSX_CPUID_CLEAR;
    137		wrmsrl(MSR_TSX_FORCE_ABORT, msr);
    138	} else if (tsx_ctrl_is_supported()) {
    139		rdmsrl(MSR_IA32_TSX_CTRL, msr);
    140		msr |= TSX_CTRL_CPUID_CLEAR;
    141		wrmsrl(MSR_IA32_TSX_CTRL, msr);
    142	}
    143}
    144
    145/*
    146 * Disable TSX development mode
    147 *
    148 * When the microcode released in Feb 2022 is applied, TSX will be disabled by
    149 * default on some processors. MSR 0x122 (TSX_CTRL) and MSR 0x123
    150 * (IA32_MCU_OPT_CTRL) can be used to re-enable TSX for development, doing so is
    151 * not recommended for production deployments. In particular, applying MD_CLEAR
    152 * flows for mitigation of the Intel TSX Asynchronous Abort (TAA) transient
    153 * execution attack may not be effective on these processors when Intel TSX is
    154 * enabled with updated microcode.
    155 */
    156static void tsx_dev_mode_disable(void)
    157{
    158	u64 mcu_opt_ctrl;
    159
    160	/* Check if RTM_ALLOW exists */
    161	if (!boot_cpu_has_bug(X86_BUG_TAA) || !tsx_ctrl_is_supported() ||
    162	    !cpu_feature_enabled(X86_FEATURE_SRBDS_CTRL))
    163		return;
    164
    165	rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_opt_ctrl);
    166
    167	if (mcu_opt_ctrl & RTM_ALLOW) {
    168		mcu_opt_ctrl &= ~RTM_ALLOW;
    169		wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_opt_ctrl);
    170		setup_force_cpu_cap(X86_FEATURE_RTM_ALWAYS_ABORT);
    171	}
    172}
    173
    174void __init tsx_init(void)
    175{
    176	char arg[5] = {};
    177	int ret;
    178
    179	tsx_dev_mode_disable();
    180
    181	/*
    182	 * Hardware will always abort a TSX transaction when the CPUID bit
    183	 * RTM_ALWAYS_ABORT is set. In this case, it is better not to enumerate
    184	 * CPUID.RTM and CPUID.HLE bits. Clear them here.
    185	 */
    186	if (boot_cpu_has(X86_FEATURE_RTM_ALWAYS_ABORT)) {
    187		tsx_ctrl_state = TSX_CTRL_RTM_ALWAYS_ABORT;
    188		tsx_clear_cpuid();
    189		setup_clear_cpu_cap(X86_FEATURE_RTM);
    190		setup_clear_cpu_cap(X86_FEATURE_HLE);
    191		return;
    192	}
    193
    194	if (!tsx_ctrl_is_supported()) {
    195		tsx_ctrl_state = TSX_CTRL_NOT_SUPPORTED;
    196		return;
    197	}
    198
    199	ret = cmdline_find_option(boot_command_line, "tsx", arg, sizeof(arg));
    200	if (ret >= 0) {
    201		if (!strcmp(arg, "on")) {
    202			tsx_ctrl_state = TSX_CTRL_ENABLE;
    203		} else if (!strcmp(arg, "off")) {
    204			tsx_ctrl_state = TSX_CTRL_DISABLE;
    205		} else if (!strcmp(arg, "auto")) {
    206			tsx_ctrl_state = x86_get_tsx_auto_mode();
    207		} else {
    208			tsx_ctrl_state = TSX_CTRL_DISABLE;
    209			pr_err("invalid option, defaulting to off\n");
    210		}
    211	} else {
    212		/* tsx= not provided */
    213		if (IS_ENABLED(CONFIG_X86_INTEL_TSX_MODE_AUTO))
    214			tsx_ctrl_state = x86_get_tsx_auto_mode();
    215		else if (IS_ENABLED(CONFIG_X86_INTEL_TSX_MODE_OFF))
    216			tsx_ctrl_state = TSX_CTRL_DISABLE;
    217		else
    218			tsx_ctrl_state = TSX_CTRL_ENABLE;
    219	}
    220
    221	if (tsx_ctrl_state == TSX_CTRL_DISABLE) {
    222		tsx_disable();
    223
    224		/*
    225		 * tsx_disable() will change the state of the RTM and HLE CPUID
    226		 * bits. Clear them here since they are now expected to be not
    227		 * set.
    228		 */
    229		setup_clear_cpu_cap(X86_FEATURE_RTM);
    230		setup_clear_cpu_cap(X86_FEATURE_HLE);
    231	} else if (tsx_ctrl_state == TSX_CTRL_ENABLE) {
    232
    233		/*
    234		 * HW defaults TSX to be enabled at bootup.
    235		 * We may still need the TSX enable support
    236		 * during init for special cases like
    237		 * kexec after TSX is disabled.
    238		 */
    239		tsx_enable();
    240
    241		/*
    242		 * tsx_enable() will change the state of the RTM and HLE CPUID
    243		 * bits. Force them here since they are now expected to be set.
    244		 */
    245		setup_force_cpu_cap(X86_FEATURE_RTM);
    246		setup_force_cpu_cap(X86_FEATURE_HLE);
    247	}
    248}
    249
    250void tsx_ap_init(void)
    251{
    252	tsx_dev_mode_disable();
    253
    254	if (tsx_ctrl_state == TSX_CTRL_ENABLE)
    255		tsx_enable();
    256	else if (tsx_ctrl_state == TSX_CTRL_DISABLE)
    257		tsx_disable();
    258	else if (tsx_ctrl_state == TSX_CTRL_RTM_ALWAYS_ABORT)
    259		/* See comment over that function for more details. */
    260		tsx_clear_cpuid();
    261}