[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250422082216.1954310-20-xin@zytor.com>
Date: Tue, 22 Apr 2025 01:22:00 -0700
From: "Xin Li (Intel)" <xin@...or.com>
To: linux-kernel@...r.kernel.org, kvm@...r.kernel.org,
linux-perf-users@...r.kernel.org, linux-hyperv@...r.kernel.org,
virtualization@...ts.linux.dev, linux-pm@...r.kernel.org,
linux-edac@...r.kernel.org, xen-devel@...ts.xenproject.org,
linux-acpi@...r.kernel.org, linux-hwmon@...r.kernel.org,
netdev@...r.kernel.org, platform-driver-x86@...r.kernel.org
Cc: tglx@...utronix.de, mingo@...hat.com, bp@...en8.de,
dave.hansen@...ux.intel.com, x86@...nel.org, hpa@...or.com,
acme@...nel.org, jgross@...e.com, andrew.cooper3@...rix.com,
peterz@...radead.org, namhyung@...nel.org, mark.rutland@....com,
alexander.shishkin@...ux.intel.com, jolsa@...nel.org,
irogers@...gle.com, adrian.hunter@...el.com, kan.liang@...ux.intel.com,
wei.liu@...nel.org, ajay.kaher@...adcom.com,
bcm-kernel-feedback-list@...adcom.com, tony.luck@...el.com,
pbonzini@...hat.com, vkuznets@...hat.com, seanjc@...gle.com,
luto@...nel.org, boris.ostrovsky@...cle.com, kys@...rosoft.com,
haiyangz@...rosoft.com, decui@...rosoft.com
Subject: [RFC PATCH v2 19/34] x86/extable: Add support for immediate form MSR instructions
Signed-off-by: Xin Li (Intel) <xin@...or.com>
---
arch/x86/include/asm/msr.h | 18 ++++++++++++++++++
arch/x86/mm/extable.c | 39 +++++++++++++++++++++++++++++++++-----
2 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index c955339be9c9..8f7a67b1c61c 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -78,6 +78,24 @@ static inline void do_trace_rdpmc(u32 msr, u64 val, int failed) {}
extern u64 xen_read_pmc(int counter);
#endif
+/*
+ * Called only from an MSR fault handler, the instruction pointer points to
+ * the MSR access instruction that caused the fault.
+ */
+static __always_inline bool is_msr_imm_insn(void *ip)
+{
+ /*
+ * A full decoder for immediate form MSR instructions appears excessive.
+ */
+#ifdef CONFIG_X86_64
+ const u8 msr_imm_insn_prefix[] = { 0xc4, 0xe7 };
+
+ return !memcmp(ip, msr_imm_insn_prefix, sizeof(msr_imm_insn_prefix));
+#else
+ return false;
+#endif
+}
+
/*
* __rdmsr() and __wrmsr() are the two primitives which are the bare minimum MSR
* accessors and should not have any tracing or other functionality piggybacking
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index bf8dab18be97..f1743babafc8 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -167,23 +167,52 @@ static bool ex_handler_uaccess(const struct exception_table_entry *fixup,
static bool ex_handler_msr(const struct exception_table_entry *fixup,
struct pt_regs *regs, bool wrmsr, bool safe, int reg)
{
+ bool imm_insn = is_msr_imm_insn((void *)regs->ip);
+ u32 msr;
+
+ if (imm_insn)
+ /*
+ * The 32-bit immediate specifying a MSR is encoded into
+ * byte 5 ~ 8 of an immediate form MSR instruction.
+ */
+ msr = *(u32 *)(regs->ip + 5);
+ else
+ msr = (u32)regs->cx;
+
if (__ONCE_LITE_IF(!safe && wrmsr)) {
- pr_warn("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
- (unsigned int)regs->cx, (unsigned int)regs->dx,
- (unsigned int)regs->ax, regs->ip, (void *)regs->ip);
+ /*
+ * To maintain consistency with existing RDMSR and WRMSR(NS) instructions,
+ * the register operand for immediate form MSR instructions is ALWAYS
+ * encoded as RAX in <asm/msr.h> for reading or writing the MSR value.
+ */
+ u64 msr_val = regs->ax;
+
+ if (!imm_insn) {
+ /*
+ * On processors that support the Intel 64 architecture, the
+ * high-order 32 bits of each of RAX and RDX are ignored.
+ */
+ msr_val &= 0xffffffff;
+ msr_val |= (u64)regs->dx << 32;
+ }
+
+ pr_warn("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%016llx) at rIP: 0x%lx (%pS)\n",
+ msr, msr_val, regs->ip, (void *)regs->ip);
show_stack_regs(regs);
}
if (__ONCE_LITE_IF(!safe && !wrmsr)) {
pr_warn("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n",
- (unsigned int)regs->cx, regs->ip, (void *)regs->ip);
+ msr, regs->ip, (void *)regs->ip);
show_stack_regs(regs);
}
if (!wrmsr) {
/* Pretend that the read succeeded and returned 0. */
regs->ax = 0;
- regs->dx = 0;
+
+ if (!imm_insn)
+ regs->dx = 0;
}
if (safe)
--
2.49.0
Powered by blists - more mailing lists