summaryrefslogtreecommitdiffstats
path: root/arch/x86/include/asm/msr.h
diff options
context:
space:
mode:
authorXin Li <xin3.li@intel.com>2023-12-05 11:49:50 +0100
committerThomas Gleixner <tglx@linutronix.de>2024-01-25 19:10:29 +0100
commita4cb5ece145828cae35503857debf3d49c9d1c5f (patch)
treec6fdc9b00cc4efc65f4ff43574809df8e7fa3d0f /arch/x86/include/asm/msr.h
parentLinux 6.8-rc1 (diff)
downloadlinux-a4cb5ece145828cae35503857debf3d49c9d1c5f.tar.xz
linux-a4cb5ece145828cae35503857debf3d49c9d1c5f.zip
x86/cpufeatures,opcode,msr: Add the WRMSRNS instruction support
WRMSRNS is an instruction that behaves exactly like WRMSR, with the only difference being that it is not a serializing instruction by default. Under certain conditions, WRMSRNS may replace WRMSR to improve performance. Add its CPU feature bit, opcode to the x86 opcode map, and an always inline API __wrmsrns() to embed WRMSRNS into the code. Signed-off-by: Xin Li <xin3.li@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Shan Kang <shan.kang@intel.com> Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Acked-by: Borislav Petkov (AMD) <bp@alien8.de> Link: https://lore.kernel.org/r/20231205105030.8698-2-xin3.li@intel.com
Diffstat (limited to 'arch/x86/include/asm/msr.h')
-rw-r--r--arch/x86/include/asm/msr.h18
1 files changed, 18 insertions, 0 deletions
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 65ec1965cd28..c284ff9ebe67 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -97,6 +97,19 @@ static __always_inline void __wrmsr(unsigned int msr, u32 low, u32 high)
: : "c" (msr), "a"(low), "d" (high) : "memory");
}
+/*
+ * WRMSRNS behaves exactly like WRMSR with the only difference being
+ * that it is not a serializing instruction by default.
+ */
+static __always_inline void __wrmsrns(u32 msr, u32 low, u32 high)
+{
+ /* Instruction opcode for WRMSRNS; supported in binutils >= 2.40. */
+ asm volatile("1: .byte 0x0f,0x01,0xc6\n"
+ "2:\n"
+ _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_WRMSR)
+ : : "c" (msr), "a"(low), "d" (high));
+}
+
#define native_rdmsr(msr, val1, val2) \
do { \
u64 __val = __rdmsr((msr)); \
@@ -297,6 +310,11 @@ do { \
#endif /* !CONFIG_PARAVIRT_XXL */
+static __always_inline void wrmsrns(u32 msr, u64 val)
+{
+ __wrmsrns(msr, val, val >> 32);
+}
+
/*
* 64-bit version of wrmsr_safe():
*/