Skip to content

Commit efe5088

Browse files
andyhhpKAGA-KOKO
authored andcommitted
x86/msr: Switch between WRMSRNS and WRMSR with the alternatives mechanism
Per the discussion about FRED MSR writes with WRMSRNS instruction [1], use the alternatives mechanism to choose WRMSRNS when it's available, otherwise fallback to WRMSR. Remove the dependency on X86_FEATURE_WRMSRNS as WRMSRNS is no longer dependent on FRED. [1] https://lore.kernel.org/lkml/[email protected]/ Use DS prefix to pad WRMSR instead of a NOP. The prefix is ignored. At least that's the current information from the hardware folks. Signed-off-by: Andrew Cooper <[email protected]> Signed-off-by: Xin Li (Intel) <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent 0dfac6f commit efe5088

File tree

3 files changed

+11
-16
lines changed

3 files changed

+11
-16
lines changed

arch/x86/include/asm/msr.h

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,19 +99,6 @@ static __always_inline void __wrmsr(unsigned int msr, u32 low, u32 high)
9999
: : "c" (msr), "a"(low), "d" (high) : "memory");
100100
}
101101

102-
/*
103-
* WRMSRNS behaves exactly like WRMSR with the only difference being
104-
* that it is not a serializing instruction by default.
105-
*/
106-
static __always_inline void __wrmsrns(u32 msr, u32 low, u32 high)
107-
{
108-
/* Instruction opcode for WRMSRNS; supported in binutils >= 2.40. */
109-
asm volatile("1: .byte 0x0f,0x01,0xc6\n"
110-
"2:\n"
111-
_ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_WRMSR)
112-
: : "c" (msr), "a"(low), "d" (high));
113-
}
114-
115102
#define native_rdmsr(msr, val1, val2) \
116103
do { \
117104
u64 __val = __rdmsr((msr)); \
@@ -312,9 +299,19 @@ do { \
312299

313300
#endif /* !CONFIG_PARAVIRT_XXL */
314301

302+
/* Instruction opcode for WRMSRNS supported in binutils >= 2.40 */
303+
#define WRMSRNS _ASM_BYTES(0x0f,0x01,0xc6)
304+
305+
/* Non-serializing WRMSR, when available. Falls back to a serializing WRMSR. */
315306
static __always_inline void wrmsrns(u32 msr, u64 val)
316307
{
317-
__wrmsrns(msr, val, val >> 32);
308+
/*
309+
* WRMSR is 2 bytes. WRMSRNS is 3 bytes. Pad WRMSR with a redundant
310+
* DS prefix to avoid a trailing NOP.
311+
*/
312+
asm volatile("1: " ALTERNATIVE("ds wrmsr", WRMSRNS, X86_FEATURE_WRMSRNS)
313+
"2: " _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_WRMSR)
314+
: : "c" (msr), "a" ((u32)val), "d" ((u32)(val >> 32)));
318315
}
319316

320317
/*

arch/x86/include/asm/switch_to.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ static inline void update_task_stack(struct task_struct *task)
7171
this_cpu_write(cpu_tss_rw.x86_tss.sp1, task->thread.sp0);
7272
#else
7373
if (cpu_feature_enabled(X86_FEATURE_FRED)) {
74-
/* WRMSRNS is a baseline feature for FRED. */
7574
wrmsrns(MSR_IA32_FRED_RSP0, (unsigned long)task_stack_page(task) + THREAD_SIZE);
7675
} else if (cpu_feature_enabled(X86_FEATURE_XENPV)) {
7776
/* Xen PV enters the kernel on the thread stack. */

arch/x86/kernel/cpu/cpuid-deps.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ static const struct cpuid_dep cpuid_deps[] = {
8383
{ X86_FEATURE_AMX_TILE, X86_FEATURE_XFD },
8484
{ X86_FEATURE_SHSTK, X86_FEATURE_XSAVES },
8585
{ X86_FEATURE_FRED, X86_FEATURE_LKGS },
86-
{ X86_FEATURE_FRED, X86_FEATURE_WRMSRNS },
8786
{}
8887
};
8988

0 commit comments

Comments
 (0)