Re: UMIP and clearcpuid=

From: Peter Zijlstra

Date: Thu Jun 11 2026 - 14:41:08 EST


On Thu, Jun 11, 2026 at 09:09:46AM -0700, Borislav Petkov wrote:

> > It is really annoying having to disable UMIP though, its bugged me, just
> > not enough to ever actually do anything about it.
>
> Well, what else could we do? Whitelist processes, make it more fine-grained or
> so...?

Perhaps just one print per task might be a good start? Something like
so?

I don't think anything hits this hard enough to matter performance wise;
but the wine stuff can hit them often enough that the dmesg spam is
annoying, and there's really nothing much you can do about it.

This is somewhat similar to the split lock stuff, yeah, they're bad, but
nobody is going to be fixing those games.

And UMIP really is useful; these are gnarly instructions you really
don't want, so as along as it all runs it should be fine. I suppose I
should go re-enable it on my own machine and actually spend some time on
it if/when I find another game that flat out doesn't work with the
emulation.

---
diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index 3ce99cbcf187..83517d5b8eae 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -90,49 +90,6 @@ static const char * const umip_insns[5] = {
[UMIP_INST_STR] = "STR",
};

-#define umip_pr_err(regs, fmt, ...) \
- umip_printk(regs, KERN_ERR, fmt, ##__VA_ARGS__)
-#define umip_pr_debug(regs, fmt, ...) \
- umip_printk(regs, KERN_DEBUG, fmt, ##__VA_ARGS__)
-
-/**
- * umip_printk() - Print a rate-limited message
- * @regs: Register set with the context in which the warning is printed
- * @log_level: Kernel log level to print the message
- * @fmt: The text string to print
- *
- * Print the text contained in @fmt. The print rate is limited to bursts of 5
- * messages every two minutes. The purpose of this customized version of
- * printk() is to print messages when user space processes use any of the
- * UMIP-protected instructions. Thus, the printed text is prepended with the
- * task name and process ID number of the current task as well as the
- * instruction and stack pointers in @regs as seen when entering kernel mode.
- *
- * Returns:
- *
- * None.
- */
-static __printf(3, 4)
-void umip_printk(const struct pt_regs *regs, const char *log_level,
- const char *fmt, ...)
-{
- /* Bursts of 5 messages every two minutes */
- static DEFINE_RATELIMIT_STATE(ratelimit, 2 * 60 * HZ, 5);
- struct task_struct *tsk = current;
- struct va_format vaf;
- va_list args;
-
- if (!__ratelimit(&ratelimit))
- return;
-
- va_start(args, fmt);
- vaf.fmt = fmt;
- vaf.va = &args;
- printk("%s" pr_fmt("%s[%d] ip:%lx sp:%lx: %pV"), log_level, tsk->comm,
- task_pid_nr(tsk), regs->ip, regs->sp, &vaf);
- va_end(args);
-}
-
/**
* identify_insn() - Identify a UMIP-protected instruction
* @insn: Instruction structure with opcode and ModRM byte.
@@ -322,8 +279,9 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV)))
return;

- umip_pr_err(regs, "segfault in emulation. error%x\n",
- X86_PF_USER | X86_PF_WRITE);
+ pr_err("%s[%d] ip:%lx sp:%lx: segfault in emulation. error%x\n",
+ tsk->comm, task_pid_nr(tsk), regs->ip, regs->sp,
+ X86_PF_USER | X86_PF_WRITE);
}

/**
@@ -375,10 +333,13 @@ bool fixup_umip_exception(struct pt_regs *regs)
if (umip_inst < 0)
return false;

- umip_pr_debug(regs, "%s instruction cannot be used by applications.\n",
- umip_insns[umip_inst]);
-
- umip_pr_debug(regs, "For now, expensive software emulation returns the result.\n");
+ if (!current->reported_umip_emu) {
+ pr_debug("%s[%d] ip:%lx sp:%lx: %s instruction cannot be used by application; "
+ "will be emulated.\n",
+ current->comm, task_pid_nr(current), regs->ip, regs->sp,
+ umip_insns[umip_inst]);
+ current->reported_umip_emu = 1;
+ }

if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size,
user_64bit_mode(regs)))
diff --git a/include/linux/sched.h b/include/linux/sched.h
index c88fc10e9c38..f6ef5b519ad6 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1044,6 +1044,9 @@ struct task_struct {
#ifdef CONFIG_X86_BUS_LOCK_DETECT
unsigned reported_split_lock:1;
#endif
+#ifdef CONFIG_X86_UMIP
+ unsigned reported_umip_emu:1;
+#endif
#ifdef CONFIG_TASK_DELAY_ACCT
/* delay due to memory thrashing */
unsigned in_thrashing:1;