diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index d317dc3d06a3..a6072c4e0a97 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -645,6 +645,36 @@ static bool fixup_iopl_exception(struct pt_regs *regs) return true; } +static bool fixup_rdtsc_exception(struct pt_regs *regs) +{ + unsigned int bytes; + unsigned long ip; + u32 eax, ecx, edx; + + if (insn_get_effective_ip(regs, &ip)) + return false; + + if (get_user(bytes, (const int __user *)ip)) + return false; + + if ((bytes & 0xFFFF) == 0x310f) { + asm volatile ("rdtsc" : "=a" (eax), "=d" (edx) ::); + regs->ax = eax; + regs->dx = edx; + regs->ip += 2; + return true; + } else if ((bytes & 0xFFFFFF) == 0xf9010f) { + asm volatile ("rdtscp" : "=a" (eax), "=d" (edx), "=c" (ecx)::); + regs->ax = eax; + regs->cx = ecx; + regs->dx = edx; + regs->ip += 3; + return true; + } + + return false; +} + /* * The unprivileged ENQCMD instruction generates #GPs if the * IA32_PASID MSR has not been populated. If possible, populate @@ -752,6 +782,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) if (fixup_iopl_exception(regs)) goto exit; + if (fixup_rdtsc_exception(regs)) + goto exit; + if (fixup_vdso_exception(regs, X86_TRAP_GP, error_code, 0)) goto exit;