[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH v2 19/34] x86/extable: Add support for immediate form MSR instructions
Signed-off-by: Xin Li (Intel) <xin@xxxxxxxxx> --- 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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |