xref: /openbmc/linux/arch/x86/kernel/cpu/tsx.c (revision bb5525a5)
195c5824fSPawan Gupta // SPDX-License-Identifier: GPL-2.0
295c5824fSPawan Gupta /*
395c5824fSPawan Gupta  * Intel Transactional Synchronization Extensions (TSX) control.
495c5824fSPawan Gupta  *
529364930SPawan Gupta  * Copyright (C) 2019-2021 Intel Corporation
695c5824fSPawan Gupta  *
795c5824fSPawan Gupta  * Author:
895c5824fSPawan Gupta  *	Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
995c5824fSPawan Gupta  */
1095c5824fSPawan Gupta 
1195c5824fSPawan Gupta #include <linux/cpufeature.h>
1295c5824fSPawan Gupta 
1395c5824fSPawan Gupta #include <asm/cmdline.h>
14*bb5525a5SAshok Raj #include <asm/cpu.h>
1595c5824fSPawan Gupta 
1695c5824fSPawan Gupta #include "cpu.h"
1795c5824fSPawan Gupta 
18d157aa0fSBorislav Petkov #undef pr_fmt
19d157aa0fSBorislav Petkov #define pr_fmt(fmt) "tsx: " fmt
20d157aa0fSBorislav Petkov 
2195c5824fSPawan Gupta enum tsx_ctrl_states tsx_ctrl_state __ro_after_init = TSX_CTRL_NOT_SUPPORTED;
2295c5824fSPawan Gupta 
tsx_disable(void)23400331f8SPawan Gupta static void tsx_disable(void)
2495c5824fSPawan Gupta {
2595c5824fSPawan Gupta 	u64 tsx;
2695c5824fSPawan Gupta 
2795c5824fSPawan Gupta 	rdmsrl(MSR_IA32_TSX_CTRL, tsx);
2895c5824fSPawan Gupta 
2995c5824fSPawan Gupta 	/* Force all transactions to immediately abort */
3095c5824fSPawan Gupta 	tsx |= TSX_CTRL_RTM_DISABLE;
3195c5824fSPawan Gupta 
3295c5824fSPawan Gupta 	/*
3395c5824fSPawan Gupta 	 * Ensure TSX support is not enumerated in CPUID.
3495c5824fSPawan Gupta 	 * This is visible to userspace and will ensure they
3595c5824fSPawan Gupta 	 * do not waste resources trying TSX transactions that
3695c5824fSPawan Gupta 	 * will always abort.
3795c5824fSPawan Gupta 	 */
3895c5824fSPawan Gupta 	tsx |= TSX_CTRL_CPUID_CLEAR;
3995c5824fSPawan Gupta 
4095c5824fSPawan Gupta 	wrmsrl(MSR_IA32_TSX_CTRL, tsx);
4195c5824fSPawan Gupta }
4295c5824fSPawan Gupta 
tsx_enable(void)43400331f8SPawan Gupta static void tsx_enable(void)
4495c5824fSPawan Gupta {
4595c5824fSPawan Gupta 	u64 tsx;
4695c5824fSPawan Gupta 
4795c5824fSPawan Gupta 	rdmsrl(MSR_IA32_TSX_CTRL, tsx);
4895c5824fSPawan Gupta 
4995c5824fSPawan Gupta 	/* Enable the RTM feature in the cpu */
5095c5824fSPawan Gupta 	tsx &= ~TSX_CTRL_RTM_DISABLE;
5195c5824fSPawan Gupta 
5295c5824fSPawan Gupta 	/*
5395c5824fSPawan Gupta 	 * Ensure TSX support is enumerated in CPUID.
5495c5824fSPawan Gupta 	 * This is visible to userspace and will ensure they
5595c5824fSPawan Gupta 	 * can enumerate and use the TSX feature.
5695c5824fSPawan Gupta 	 */
5795c5824fSPawan Gupta 	tsx &= ~TSX_CTRL_CPUID_CLEAR;
5895c5824fSPawan Gupta 
5995c5824fSPawan Gupta 	wrmsrl(MSR_IA32_TSX_CTRL, tsx);
6095c5824fSPawan Gupta }
6195c5824fSPawan Gupta 
x86_get_tsx_auto_mode(void)62db616173SMichal Hocko static enum tsx_ctrl_states x86_get_tsx_auto_mode(void)
63db616173SMichal Hocko {
64db616173SMichal Hocko 	if (boot_cpu_has_bug(X86_BUG_TAA))
65db616173SMichal Hocko 		return TSX_CTRL_DISABLE;
66db616173SMichal Hocko 
67db616173SMichal Hocko 	return TSX_CTRL_ENABLE;
68db616173SMichal Hocko }
69db616173SMichal Hocko 
70258f3b8cSPawan Gupta /*
71258f3b8cSPawan Gupta  * Disabling TSX is not a trivial business.
72258f3b8cSPawan Gupta  *
73258f3b8cSPawan Gupta  * First of all, there's a CPUID bit: X86_FEATURE_RTM_ALWAYS_ABORT
74258f3b8cSPawan Gupta  * which says that TSX is practically disabled (all transactions are
75258f3b8cSPawan Gupta  * aborted by default). When that bit is set, the kernel unconditionally
76258f3b8cSPawan Gupta  * disables TSX.
77258f3b8cSPawan Gupta  *
78258f3b8cSPawan Gupta  * In order to do that, however, it needs to dance a bit:
79258f3b8cSPawan Gupta  *
80258f3b8cSPawan Gupta  * 1. The first method to disable it is through MSR_TSX_FORCE_ABORT and
81258f3b8cSPawan Gupta  * the MSR is present only when *two* CPUID bits are set:
82258f3b8cSPawan Gupta  *
83258f3b8cSPawan Gupta  * - X86_FEATURE_RTM_ALWAYS_ABORT
84258f3b8cSPawan Gupta  * - X86_FEATURE_TSX_FORCE_ABORT
85258f3b8cSPawan Gupta  *
86258f3b8cSPawan Gupta  * 2. The second method is for CPUs which do not have the above-mentioned
87258f3b8cSPawan Gupta  * MSR: those use a different MSR - MSR_IA32_TSX_CTRL and disable TSX
88258f3b8cSPawan Gupta  * through that one. Those CPUs can also have the initially mentioned
89258f3b8cSPawan Gupta  * CPUID bit X86_FEATURE_RTM_ALWAYS_ABORT set and for those the same strategy
90258f3b8cSPawan Gupta  * applies: TSX gets disabled unconditionally.
91258f3b8cSPawan Gupta  *
92258f3b8cSPawan Gupta  * When either of the two methods are present, the kernel disables TSX and
93258f3b8cSPawan Gupta  * clears the respective RTM and HLE feature flags.
94258f3b8cSPawan Gupta  *
95258f3b8cSPawan Gupta  * An additional twist in the whole thing presents late microcode loading
96258f3b8cSPawan Gupta  * which, when done, may cause for the X86_FEATURE_RTM_ALWAYS_ABORT CPUID
97258f3b8cSPawan Gupta  * bit to be set after the update.
98258f3b8cSPawan Gupta  *
99258f3b8cSPawan Gupta  * A subsequent hotplug operation on any logical CPU except the BSP will
100258f3b8cSPawan Gupta  * cause for the supported CPUID feature bits to get re-detected and, if
101258f3b8cSPawan Gupta  * RTM and HLE get cleared all of a sudden, but, userspace did consult
102258f3b8cSPawan Gupta  * them before the update, then funny explosions will happen. Long story
103258f3b8cSPawan Gupta  * short: the kernel doesn't modify CPUID feature bits after booting.
104258f3b8cSPawan Gupta  *
105258f3b8cSPawan Gupta  * That's why, this function's call in init_intel() doesn't clear the
106258f3b8cSPawan Gupta  * feature flags.
107258f3b8cSPawan Gupta  */
tsx_clear_cpuid(void)108400331f8SPawan Gupta static void tsx_clear_cpuid(void)
10929364930SPawan Gupta {
11029364930SPawan Gupta 	u64 msr;
11129364930SPawan Gupta 
11229364930SPawan Gupta 	/*
11329364930SPawan Gupta 	 * MSR_TFA_TSX_CPUID_CLEAR bit is only present when both CPUID
11429364930SPawan Gupta 	 * bits RTM_ALWAYS_ABORT and TSX_FORCE_ABORT are present.
11529364930SPawan Gupta 	 */
11629364930SPawan Gupta 	if (boot_cpu_has(X86_FEATURE_RTM_ALWAYS_ABORT) &&
11729364930SPawan Gupta 	    boot_cpu_has(X86_FEATURE_TSX_FORCE_ABORT)) {
11829364930SPawan Gupta 		rdmsrl(MSR_TSX_FORCE_ABORT, msr);
11929364930SPawan Gupta 		msr |= MSR_TFA_TSX_CPUID_CLEAR;
12029364930SPawan Gupta 		wrmsrl(MSR_TSX_FORCE_ABORT, msr);
121aaa65d17SPawan Gupta 	} else if (cpu_feature_enabled(X86_FEATURE_MSR_TSX_CTRL)) {
122258f3b8cSPawan Gupta 		rdmsrl(MSR_IA32_TSX_CTRL, msr);
123258f3b8cSPawan Gupta 		msr |= TSX_CTRL_CPUID_CLEAR;
124258f3b8cSPawan Gupta 		wrmsrl(MSR_IA32_TSX_CTRL, msr);
12529364930SPawan Gupta 	}
12629364930SPawan Gupta }
12729364930SPawan Gupta 
128400331f8SPawan Gupta /*
129400331f8SPawan Gupta  * Disable TSX development mode
130400331f8SPawan Gupta  *
131400331f8SPawan Gupta  * When the microcode released in Feb 2022 is applied, TSX will be disabled by
132400331f8SPawan Gupta  * default on some processors. MSR 0x122 (TSX_CTRL) and MSR 0x123
133400331f8SPawan Gupta  * (IA32_MCU_OPT_CTRL) can be used to re-enable TSX for development, doing so is
134400331f8SPawan Gupta  * not recommended for production deployments. In particular, applying MD_CLEAR
135400331f8SPawan Gupta  * flows for mitigation of the Intel TSX Asynchronous Abort (TAA) transient
136400331f8SPawan Gupta  * execution attack may not be effective on these processors when Intel TSX is
137400331f8SPawan Gupta  * enabled with updated microcode.
138400331f8SPawan Gupta  */
tsx_dev_mode_disable(void)139400331f8SPawan Gupta static void tsx_dev_mode_disable(void)
140400331f8SPawan Gupta {
141400331f8SPawan Gupta 	u64 mcu_opt_ctrl;
142400331f8SPawan Gupta 
143400331f8SPawan Gupta 	/* Check if RTM_ALLOW exists */
144aaa65d17SPawan Gupta 	if (!boot_cpu_has_bug(X86_BUG_TAA) ||
145aaa65d17SPawan Gupta 	    !cpu_feature_enabled(X86_FEATURE_MSR_TSX_CTRL) ||
146400331f8SPawan Gupta 	    !cpu_feature_enabled(X86_FEATURE_SRBDS_CTRL))
147400331f8SPawan Gupta 		return;
148400331f8SPawan Gupta 
149400331f8SPawan Gupta 	rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_opt_ctrl);
150400331f8SPawan Gupta 
151400331f8SPawan Gupta 	if (mcu_opt_ctrl & RTM_ALLOW) {
152400331f8SPawan Gupta 		mcu_opt_ctrl &= ~RTM_ALLOW;
153400331f8SPawan Gupta 		wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_opt_ctrl);
154400331f8SPawan Gupta 		setup_force_cpu_cap(X86_FEATURE_RTM_ALWAYS_ABORT);
155400331f8SPawan Gupta 	}
156400331f8SPawan Gupta }
157400331f8SPawan Gupta 
tsx_init(void)15895c5824fSPawan Gupta void __init tsx_init(void)
15995c5824fSPawan Gupta {
1607531a359SPawan Gupta 	char arg[5] = {};
16195c5824fSPawan Gupta 	int ret;
16295c5824fSPawan Gupta 
163400331f8SPawan Gupta 	tsx_dev_mode_disable();
164400331f8SPawan Gupta 
16529364930SPawan Gupta 	/*
166258f3b8cSPawan Gupta 	 * Hardware will always abort a TSX transaction when the CPUID bit
167258f3b8cSPawan Gupta 	 * RTM_ALWAYS_ABORT is set. In this case, it is better not to enumerate
168258f3b8cSPawan Gupta 	 * CPUID.RTM and CPUID.HLE bits. Clear them here.
16929364930SPawan Gupta 	 */
170258f3b8cSPawan Gupta 	if (boot_cpu_has(X86_FEATURE_RTM_ALWAYS_ABORT)) {
17129364930SPawan Gupta 		tsx_ctrl_state = TSX_CTRL_RTM_ALWAYS_ABORT;
17229364930SPawan Gupta 		tsx_clear_cpuid();
17329364930SPawan Gupta 		setup_clear_cpu_cap(X86_FEATURE_RTM);
17429364930SPawan Gupta 		setup_clear_cpu_cap(X86_FEATURE_HLE);
17595c5824fSPawan Gupta 		return;
17629364930SPawan Gupta 	}
17729364930SPawan Gupta 
178aaa65d17SPawan Gupta 	/*
179aaa65d17SPawan Gupta 	 * TSX is controlled via MSR_IA32_TSX_CTRL.  However, support for this
180aaa65d17SPawan Gupta 	 * MSR is enumerated by ARCH_CAP_TSX_MSR bit in MSR_IA32_ARCH_CAPABILITIES.
181aaa65d17SPawan Gupta 	 *
182aaa65d17SPawan Gupta 	 * TSX control (aka MSR_IA32_TSX_CTRL) is only available after a
183aaa65d17SPawan Gupta 	 * microcode update on CPUs that have their MSR_IA32_ARCH_CAPABILITIES
184aaa65d17SPawan Gupta 	 * bit MDS_NO=1. CPUs with MDS_NO=0 are not planned to get
185aaa65d17SPawan Gupta 	 * MSR_IA32_TSX_CTRL support even after a microcode update. Thus,
186aaa65d17SPawan Gupta 	 * tsx= cmdline requests will do nothing on CPUs without
187aaa65d17SPawan Gupta 	 * MSR_IA32_TSX_CTRL support.
188aaa65d17SPawan Gupta 	 */
189aaa65d17SPawan Gupta 	if (x86_read_arch_cap_msr() & ARCH_CAP_TSX_CTRL_MSR) {
190aaa65d17SPawan Gupta 		setup_force_cpu_cap(X86_FEATURE_MSR_TSX_CTRL);
191aaa65d17SPawan Gupta 	} else {
19229364930SPawan Gupta 		tsx_ctrl_state = TSX_CTRL_NOT_SUPPORTED;
19329364930SPawan Gupta 		return;
19429364930SPawan Gupta 	}
19595c5824fSPawan Gupta 
19695c5824fSPawan Gupta 	ret = cmdline_find_option(boot_command_line, "tsx", arg, sizeof(arg));
19795c5824fSPawan Gupta 	if (ret >= 0) {
19895c5824fSPawan Gupta 		if (!strcmp(arg, "on")) {
19995c5824fSPawan Gupta 			tsx_ctrl_state = TSX_CTRL_ENABLE;
20095c5824fSPawan Gupta 		} else if (!strcmp(arg, "off")) {
20195c5824fSPawan Gupta 			tsx_ctrl_state = TSX_CTRL_DISABLE;
2027531a359SPawan Gupta 		} else if (!strcmp(arg, "auto")) {
203db616173SMichal Hocko 			tsx_ctrl_state = x86_get_tsx_auto_mode();
20495c5824fSPawan Gupta 		} else {
20595c5824fSPawan Gupta 			tsx_ctrl_state = TSX_CTRL_DISABLE;
206d157aa0fSBorislav Petkov 			pr_err("invalid option, defaulting to off\n");
20795c5824fSPawan Gupta 		}
20895c5824fSPawan Gupta 	} else {
209db616173SMichal Hocko 		/* tsx= not provided */
210db616173SMichal Hocko 		if (IS_ENABLED(CONFIG_X86_INTEL_TSX_MODE_AUTO))
211db616173SMichal Hocko 			tsx_ctrl_state = x86_get_tsx_auto_mode();
212db616173SMichal Hocko 		else if (IS_ENABLED(CONFIG_X86_INTEL_TSX_MODE_OFF))
21395c5824fSPawan Gupta 			tsx_ctrl_state = TSX_CTRL_DISABLE;
214db616173SMichal Hocko 		else
215db616173SMichal Hocko 			tsx_ctrl_state = TSX_CTRL_ENABLE;
21695c5824fSPawan Gupta 	}
21795c5824fSPawan Gupta 
21895c5824fSPawan Gupta 	if (tsx_ctrl_state == TSX_CTRL_DISABLE) {
21995c5824fSPawan Gupta 		tsx_disable();
22095c5824fSPawan Gupta 
22195c5824fSPawan Gupta 		/*
2225efc6fa9SPawan Gupta 		 * tsx_disable() will change the state of the RTM and HLE CPUID
2235efc6fa9SPawan Gupta 		 * bits. Clear them here since they are now expected to be not
2245efc6fa9SPawan Gupta 		 * set.
22595c5824fSPawan Gupta 		 */
22695c5824fSPawan Gupta 		setup_clear_cpu_cap(X86_FEATURE_RTM);
2275efc6fa9SPawan Gupta 		setup_clear_cpu_cap(X86_FEATURE_HLE);
22895c5824fSPawan Gupta 	} else if (tsx_ctrl_state == TSX_CTRL_ENABLE) {
22995c5824fSPawan Gupta 
23095c5824fSPawan Gupta 		/*
23195c5824fSPawan Gupta 		 * HW defaults TSX to be enabled at bootup.
23295c5824fSPawan Gupta 		 * We may still need the TSX enable support
23395c5824fSPawan Gupta 		 * during init for special cases like
23495c5824fSPawan Gupta 		 * kexec after TSX is disabled.
23595c5824fSPawan Gupta 		 */
23695c5824fSPawan Gupta 		tsx_enable();
23795c5824fSPawan Gupta 
23895c5824fSPawan Gupta 		/*
2395efc6fa9SPawan Gupta 		 * tsx_enable() will change the state of the RTM and HLE CPUID
2405efc6fa9SPawan Gupta 		 * bits. Force them here since they are now expected to be set.
24195c5824fSPawan Gupta 		 */
24295c5824fSPawan Gupta 		setup_force_cpu_cap(X86_FEATURE_RTM);
2435efc6fa9SPawan Gupta 		setup_force_cpu_cap(X86_FEATURE_HLE);
24495c5824fSPawan Gupta 	}
24595c5824fSPawan Gupta }
246400331f8SPawan Gupta 
tsx_ap_init(void)247400331f8SPawan Gupta void tsx_ap_init(void)
248400331f8SPawan Gupta {
249400331f8SPawan Gupta 	tsx_dev_mode_disable();
250400331f8SPawan Gupta 
251400331f8SPawan Gupta 	if (tsx_ctrl_state == TSX_CTRL_ENABLE)
252400331f8SPawan Gupta 		tsx_enable();
253400331f8SPawan Gupta 	else if (tsx_ctrl_state == TSX_CTRL_DISABLE)
254400331f8SPawan Gupta 		tsx_disable();
255400331f8SPawan Gupta 	else if (tsx_ctrl_state == TSX_CTRL_RTM_ALWAYS_ABORT)
256400331f8SPawan Gupta 		/* See comment over that function for more details. */
257400331f8SPawan Gupta 		tsx_clear_cpuid();
258400331f8SPawan Gupta }
259