Skip to content

Commit 258f3b8

Browse files
pa1guptasuryasaimadhu
authored andcommitted
x86/tsx: Use MSR_TSX_CTRL to clear CPUID bits
tsx_clear_cpuid() uses MSR_TSX_FORCE_ABORT to clear CPUID.RTM and CPUID.HLE. Not all CPUs support MSR_TSX_FORCE_ABORT, alternatively use MSR_IA32_TSX_CTRL when supported. [ bp: Document how and why TSX gets disabled. ] Fixes: 2936493 ("x86/tsx: Clear CPUID bits when TSX always force aborts") Reported-by: kernel test robot <[email protected]> Signed-off-by: Pawan Gupta <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Tested-by: Neelima Krishnan <[email protected]> Cc: <[email protected]> Link: https://lore.kernel.org/r/5b323e77e251a9c8bcdda498c5cc0095be1e1d3c.1646943780.git.pawan.kumar.gupta@linux.intel.com
1 parent ce522ba commit 258f3b8

File tree

2 files changed

+48
-7
lines changed

2 files changed

+48
-7
lines changed

arch/x86/kernel/cpu/intel.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,7 @@ static void init_intel(struct cpuinfo_x86 *c)
722722
else if (tsx_ctrl_state == TSX_CTRL_DISABLE)
723723
tsx_disable();
724724
else if (tsx_ctrl_state == TSX_CTRL_RTM_ALWAYS_ABORT)
725+
/* See comment over that function for more details. */
725726
tsx_clear_cpuid();
726727

727728
split_lock_init();

arch/x86/kernel/cpu/tsx.c

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void tsx_enable(void)
5858
wrmsrl(MSR_IA32_TSX_CTRL, tsx);
5959
}
6060

61-
static bool __init tsx_ctrl_is_supported(void)
61+
static bool tsx_ctrl_is_supported(void)
6262
{
6363
u64 ia32_cap = x86_read_arch_cap_msr();
6464

@@ -84,6 +84,44 @@ static enum tsx_ctrl_states x86_get_tsx_auto_mode(void)
8484
return TSX_CTRL_ENABLE;
8585
}
8686

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+
*/
87125
void tsx_clear_cpuid(void)
88126
{
89127
u64 msr;
@@ -97,6 +135,10 @@ void tsx_clear_cpuid(void)
97135
rdmsrl(MSR_TSX_FORCE_ABORT, msr);
98136
msr |= MSR_TFA_TSX_CPUID_CLEAR;
99137
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);
100142
}
101143
}
102144

@@ -106,13 +148,11 @@ void __init tsx_init(void)
106148
int ret;
107149

108150
/*
109-
* Hardware will always abort a TSX transaction if both CPUID bits
110-
* RTM_ALWAYS_ABORT and TSX_FORCE_ABORT are set. In this case, it is
111-
* better not to enumerate CPUID.RTM and CPUID.HLE bits. Clear them
112-
* here.
151+
* Hardware will always abort a TSX transaction when the CPUID bit
152+
* RTM_ALWAYS_ABORT is set. In this case, it is better not to enumerate
153+
* CPUID.RTM and CPUID.HLE bits. Clear them here.
113154
*/
114-
if (boot_cpu_has(X86_FEATURE_RTM_ALWAYS_ABORT) &&
115-
boot_cpu_has(X86_FEATURE_TSX_FORCE_ABORT)) {
155+
if (boot_cpu_has(X86_FEATURE_RTM_ALWAYS_ABORT)) {
116156
tsx_ctrl_state = TSX_CTRL_RTM_ALWAYS_ABORT;
117157
tsx_clear_cpuid();
118158
setup_clear_cpu_cap(X86_FEATURE_RTM);

0 commit comments

Comments
 (0)